Skip to content

Commit 1818704

Browse files
committed
fix(rt): align transparent pointer casts
1 parent 66aec6d commit 1818704

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

kmir/src/kmir/kdist/mir-semantics/rt/data.md

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,15 +1262,78 @@ the `Value` sort.
12621262
Conversion is especially possible for the case of _Slices_ (of dynamic length) and _Arrays_ (of static length),
12631263
which have the same representation `Value::Range`.
12641264

1265+
When the cast crosses transparent wrappers (for example newtypes that just forward field `0`), the pointer's
1266+
`Place` must be realigned. `#alignTransparentPlace` rewrites the projection list until the source and target
1267+
expose the same inner value:
1268+
- if the source unwraps more than the target, append an explicit `field(0)` so the target still sees that field;
1269+
- if the target unwraps more, strip any redundant tail projections with `#popTransparentTailTo`, leaving the
1270+
canonical prefix shared by both sides.
1271+
12651272
```k
12661273
rule <k> #cast(PtrLocal(OFFSET, PLACE, MUT, META), castKindPtrToPtr, TY_SOURCE, TY_TARGET)
12671274
=>
1268-
PtrLocal(OFFSET, PLACE, MUT, #convertMetadata(META, lookupTy(TY_TARGET)))
1275+
PtrLocal(
1276+
OFFSET,
1277+
#alignTransparentPlace(
1278+
PLACE,
1279+
#lookupMaybeTy(pointeeTy(lookupTy(TY_SOURCE))),
1280+
#lookupMaybeTy(pointeeTy(lookupTy(TY_TARGET)))
1281+
),
1282+
MUT,
1283+
#convertMetadata(META, lookupTy(TY_TARGET))
1284+
)
12691285
...
12701286
</k>
12711287
requires #typesCompatible(lookupTy(TY_SOURCE), lookupTy(TY_TARGET))
12721288
[preserves-definedness] // valid map lookups checked
12731289
1290+
syntax Place ::= #alignTransparentPlace ( Place , TypeInfo , TypeInfo ) [function, total]
1291+
syntax ProjectionElems ::= #popTransparentTailTo ( ProjectionElems , TypeInfo ) [function, total]
1292+
1293+
rule #alignTransparentPlace(place(LOCAL, PROJS), typeInfoStructType(_, _, FIELD_TY .Tys, LAYOUT) #as SOURCE, TARGET)
1294+
=> #alignTransparentPlace(
1295+
place(
1296+
LOCAL,
1297+
appendP(PROJS, projectionElemField(fieldIdx(0), FIELD_TY) .ProjectionElems)
1298+
),
1299+
lookupTy(FIELD_TY),
1300+
TARGET
1301+
)
1302+
requires #transparentDepth(SOURCE) >Int #transparentDepth(TARGET)
1303+
andBool #zeroFieldOffset(LAYOUT)
1304+
1305+
rule #alignTransparentPlace(
1306+
place(LOCAL, PROJS),
1307+
SOURCE,
1308+
typeInfoStructType(_, _, FIELD_TY .Tys, LAYOUT) #as TARGET
1309+
)
1310+
=> #alignTransparentPlace(
1311+
place(LOCAL, #popTransparentTailTo(PROJS, lookupTy(FIELD_TY))),
1312+
SOURCE,
1313+
lookupTy(FIELD_TY)
1314+
)
1315+
requires #transparentDepth(SOURCE) <Int #transparentDepth(TARGET)
1316+
andBool #zeroFieldOffset(LAYOUT)
1317+
andBool PROJS =/=K #popTransparentTailTo(PROJS, lookupTy(FIELD_TY))
1318+
1319+
rule #alignTransparentPlace(PLACE, _, _) => PLACE [owise]
1320+
1321+
rule #popTransparentTailTo(
1322+
projectionElemField(fieldIdx(0), FIELD_TY) .ProjectionElems,
1323+
TARGET
1324+
)
1325+
=> .ProjectionElems
1326+
requires lookupTy(FIELD_TY) ==K TARGET
1327+
1328+
rule #popTransparentTailTo(
1329+
X:ProjectionElem REST:ProjectionElems,
1330+
TARGET
1331+
)
1332+
=> X #popTransparentTailTo(REST, TARGET)
1333+
requires REST =/=K .ProjectionElems
1334+
1335+
rule #popTransparentTailTo(PROJS, _) => PROJS [owise]
1336+
12741337
syntax Metadata ::= #convertMetadata ( Metadata , TypeInfo ) [function, total]
12751338
// -------------------------------------------------------------------------------------
12761339
```

kmir/src/kmir/kdist/mir-semantics/rt/types.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,32 @@ Pointers to arrays/slices are compatible with pointers to the element type
6161
rule #isArrayOf( _ , _ ) => false [owise]
6262
```
6363

64+
Pointers to structs with a single zero-offset field are compatible with pointers to that field's type
65+
```k
66+
rule #typesCompatible(SRC, OTHER) => true
67+
requires #zeroSizedType(SRC) orBool #zeroSizedType(OTHER)
68+
69+
rule #typesCompatible(typeInfoStructType(_, _, FIELD .Tys, LAYOUT), OTHER)
70+
=> #typesCompatible(lookupTy(FIELD), OTHER)
71+
requires #zeroFieldOffset(LAYOUT)
72+
73+
rule #typesCompatible(OTHER, typeInfoStructType(_, _, FIELD .Tys, LAYOUT))
74+
=> #typesCompatible(OTHER, lookupTy(FIELD))
75+
requires #zeroFieldOffset(LAYOUT)
76+
77+
syntax Bool ::= #zeroFieldOffset ( MaybeLayoutShape ) [function, total]
78+
79+
rule #zeroFieldOffset(LAYOUT)
80+
=> #structOffsets(LAYOUT) ==K .MachineSizes
81+
orBool #structOffsets(LAYOUT) ==K machineSize(mirInt(0)) .MachineSizes
82+
orBool #structOffsets(LAYOUT) ==K machineSize(0) .MachineSizes
83+
84+
syntax MachineSizes ::= #structOffsets ( MaybeLayoutShape ) [function, total]
85+
86+
rule #structOffsets(someLayoutShape(layoutShape(fieldsShapeArbitrary(mk(OFFSETS)), _, _, _, _))) => OFFSETS
87+
rule #structOffsets(_) => .MachineSizes [owise]
88+
```
89+
6490
## Determining types of places with projection
6591

6692
A helper function `getTyOf` traverses type metadata (using the type metadata map `Ty -> TypeInfo`) along the applied projections to determine the `Ty` of the projected place.
@@ -70,6 +96,24 @@ To make this function total, an optional `MaybeTy` is used.
7096
syntax MaybeTy ::= Ty
7197
| "TyUnknown"
7298
99+
syntax MaybeTy ::= #transparentFieldTy ( TypeInfo ) [function, total]
100+
101+
rule #transparentFieldTy(typeInfoStructType(_, _, FIELD .Tys, LAYOUT)) => FIELD
102+
requires #zeroFieldOffset(LAYOUT)
103+
rule #transparentFieldTy(_) => TyUnknown [owise]
104+
105+
syntax Int ::= #transparentDepth ( TypeInfo ) [function, total]
106+
107+
rule #transparentDepth(typeInfoStructType(_, _, FIELD .Tys, LAYOUT))
108+
=> 1 +Int #transparentDepth(lookupTy(FIELD))
109+
requires #zeroFieldOffset(LAYOUT)
110+
rule #transparentDepth(_) => 0 [owise]
111+
112+
syntax TypeInfo ::= #lookupMaybeTy ( MaybeTy ) [function, total]
113+
114+
rule #lookupMaybeTy(TY:Ty) => lookupTy(TY)
115+
rule #lookupMaybeTy(TyUnknown) => typeInfoVoidType
116+
73117
syntax MaybeTy ::= getTyOf( MaybeTy , ProjectionElems ) [function, total]
74118
// -----------------------------------------------------------
75119
rule getTyOf(TyUnknown, _ ) => TyUnknown

0 commit comments

Comments
 (0)