Analysis attempt.
First case, with M0, ie. with all type defs in the module, we have this binary representation of the types (from the linked assembly listing, ie. with resolved addresses):
Code: Select all
MODULE M0;
TYPE
Mp* = POINTER TO Mdesc;
M0p* = POINTER TO M0desc;
Mdesc* = RECORD END;
. 4 010004988H 00000H <Type: 0>
. 8 01000498CH 00000H <Type: 0>
. 12 010004990H 00000H <Type: 0>
. 16 010004994H 00000H <Type: 0>
. 20 010004998H 00000H <Type: 0>
M0desc* = RECORD (Mdesc) END;
. 24 01000499CH 00000H <Type: 0>
. 28 0100049A0H 01000499CH <Type: 0180000H>
. 32 0100049A4H 00000H <Type: 0>
. 36 0100049A8H 00000H <Type: 0>
. 40 0100049ACH 00000H <Type: 0>
M1p* = POINTER TO M1desc;
M1desc* = RECORD (M0desc) END;
. 44 0100049B0H 00000H <Type: 0>
. 48 0100049B4H 01000499CH <Type: 018000EH>
. 52 0100049B8H 0100049B0H <Type: 02C0018H>
. 56 0100049BCH 00000H <Type: 0>
. 60 0100049C0H 00000H <Type: 0>
The values at the respective extension levels are addresses of the corresponding type records (to self or parent), which are used for the type check:
Code: Select all
(* .. *)
ASSERT(mp IS M0p, 200);
. 168 010004A2CH 0F8DF0094H ldr.w r0,[pc,#148] -> 320
. 172 010004A30H 06800H ldr r0,[r0] <= get address value in mp (is POINTER TO M1desc)
. 174 010004A32H 0F8501C04H ldr.w r1,[r0,#-4] <= get address of M1desc type record from heap
. 178 010004A36H 06849H ldr r1,[r1,#4] <= get value ext. level 1 of M1desc record (address of M0desc)
. 180 010004A38H 0467BH mov r3,pc
. 182 010004A3AH 0F1B302A0H subs.w r2,r3,#160 <= get address of M0desc record
. 186 010004A3EH 04291H cmp r1,r2 <= compare addresses
. 188 010004A40H 0D001H beq.n 2 -> 194
. 190 010004A42H 0DFC8H svc 200
(* .. *)
. 320 010004AC4H 02003FD88H <Global: M0 data> <= mp
Second case, with T2 and M1:
Code: Select all
MODULE T2;
TYPE
Mp* = POINTER TO Mdesc;
M0p* = POINTER TO M0desc;
Mdesc* = RECORD END;
. 4 010004958H 00000H <Type: 0>
. 8 01000495CH 00000H <Type: 0>
. 12 010004960H 00000H <Type: 0>
. 16 010004964H 00000H <Type: 0>
. 20 010004968H 00000H <Type: 0>
M0desc* = RECORD (Mdesc) END;
. 24 01000496CH 00000H <Type: 0>
. 28 010004970H 01000496CH <Type: 0180000H>
. 32 010004974H 00000H <Type: 0>
. 36 010004978H 00000H <Type: 0>
. 40 01000497CH 00000H <Type: 0>
MODULE M1;
TYPE
M1p* = POINTER TO M1desc;
M1desc* = RECORD (M0desc) END;
. 4 010004988H 00000H <Type: 0>
. 8 01000498CH 02003FD74H <Type: 020000H> <= here (see below)
. 12 010004990H 010004988H <Type: 040000H>
. 16 010004994H 00000H <Type: 0>
. 20 010004998H 00000H <Type: 0>
Same code section as above:
Code: Select all
ASSERT(mp IS M0p, 200);
. 128 010004A04H 0F8DF0090H ldr.w r0,[pc,#144] -> 276
. 132 010004A08H 06800H ldr r0,[r0]
. 134 010004A0AH 0F8501C04H ldr.w r1,[r0,#-4]
. 138 010004A0EH 06849H ldr r1,[r1,#4]
. 140 010004A10H 0F8DF2078H ldr.w r2,[pc,#120] -> 264
. 144 010004A14H 04291H cmp r1,r2
. 146 010004A16H 0D001H beq.n 2 -> 152
. 148 010004A18H 0DFC8H svc 200
(* .. *)
. 264 010004A8CH 01000496CH <Global: T2 code>
. 276 010004A98H 02003FD88H <Global: M2 data>
At relative address 8 in M1 we have a RAM address (02003FD74H) at extension level 1 of M1desc (it's an address in the stack range in this case, inital stack pointer is 2003FD78H), which gets compared to the address of M0desc in T2 code space (01000496CH). That is, it appears that address in M1desc does not get resolved correctly. Then again, my understanding and analysis can well be wrong.