C0 Value and Pointer

This section is not the Type Inference section. This section will not discuss how the actual type of variable is inference during runtime. We only focus on the w32 (value type) and * (pointer type) here.

In C0VM.ts, everything is eventually a segment of ArrayBuffer. We use DataView to wrap up the ArrayBuffer with two benefits:

  • DataView provides an interface that allow us to read and write the ArrayBuffer

  • DataView allow us to create alias to a specific segment of ArrayBuffer

C0Pointer *t

C0Pointer is a DataView with byte-length of 8 (64-bit). However, different from what C actually do to pointer, we only use the first 6 bytes to store the memory address. The remaining 2 bytes are used to annotate the size of allocated memory block. This allow C0VM.ts to check memory-access out of bound and throw error when dereferencing (or even creating!) such pointer.

Start Index (include)End Index (exclude)Representation

0

4

Uint32 - (address) Address of Memory block this pointer is pointing to

4

6

Uint16 - (offset) Offset of the pointer on the pointed memory block

6

8

Uint16 - (size) The size of memory block

A pointer points at allocated memory segment [address, address + size) with precise address as address + offset will be represented as

[address, offset, size]

NULL Pointer

By C convention, if a pointer is 0x0000000000000000 (64-bit zero), we say this pointer is a NULL Pointer.

Since the definition of NULL pointer is subject to change in the future, it is highly recommended to use the function

export function isNullPtr(ptr: C0Pointer): boolean;

to verify whether a pointer is NULL or not.

Read Pointer

A helper function

export function read_ptr(ptr: C0Pointer): [number, number, number];

// usage example
const [addr, offset, size] = read_ptr(ptr);

is defined in utility/pointer_ops.ts. Giving the function a C0Pointer (which is, in fact, only an alias of DataView), it will return the address, offset of pointer and size of memory segment.

Function Pointer* (C1 Standard)

The Function Pointer is not supported in C0VM now, it is here for future implementation and compatibility.

Currently, I planned to use pointers with

FieldValue

Address

0x0000_0000

Offset

0x0000 to 0xFFFF

Size

0x0000

to represent the function pointers.

Int, Boolean and Char w32

int, boolean and char are all a DataView with length of 4 bytes. That is to say, they are all stored in a segment of ArrayBuffer.

In C0VM Write-up, these 4-bytes values are all annotated as w32 type.

For types of boolean and char, their value will be stored in the last byte of the 4-byte ArrayBuffer (follows little endian byte ordering).

Array t[]

For any type t with size s, we can create an array of it. The array is described by structure like this

Starting Index (Include)Ending Byte Index (Exclude)Meaning

0

4

Size of each element of the array

4

4 + n * s

An n-element array

C0Value

Defined in ./src/types/types.d.ts

C0Value is a wrapper for the actual values in C0VM with type information stored to allow us perform run-time type inference.

declare const enum C0TypeClass {
    unknown = "<unknown>",
    value = "value",
    ptr = "ptr",
    string = "string"
}

type C0Value<T extends C0TypeClass> = {
    type: C0Type<T>;
    value: DataView;
};

The type here is the inferenced data type that can be used for visualization and debug console. This will be further discussed in the Type Inference section.

In the future, some more options will be added to the C0TypeClass to make it compatible with tagged_pointer and func_pointer (C1 Standard).

Last updated