Skip to content

Commit 749bcff

Browse files
committed
fix(rt): align transparent pointer casts
1 parent 5b8ce03 commit 749bcff

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
@@ -1265,15 +1265,78 @@ the `Value` sort.
12651265
Conversion is especially possible for the case of _Slices_ (of dynamic length) and _Arrays_ (of static length),
12661266
which have the same representation `Value::Range`.
12671267

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

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)