Hi - author of the VM here! The whole LLVM stack (including codegen at the start, all the way through to symbol fixup on the linker side) assumes that addresses are byte addresses. And indeed for the VM to be useful, we want to be able to compile and run software written for POSIX C (e.g. Linux), which assumes an 8-bit byte. This conflicts with the architecture of the VM where the smallest directly addressable unit is a 32-bit word.
We manage this at the MIR level - we have for example LW, LH and LB MIR instructions that load (aligned) 32-bit words, 16-bit halfwords and 8-bit bytes from byte addresses that LLVM generates, respectively. LW is implemented as a simple assembly instruction (since we can load 32-bit words directly), whereas LH and LB are a lot more complicated since they need to load the whole 32 bit word and then compute individual bits depending on the subaddress within the word. But the end result is always that generated instructions reference only (32-bit aligned) byte addresses.
So this means:
- that the VM has to divide those byte addresses by 4 to obtain word addresses (i.e. indexes into our 32-bit word memory)
- the bottom two bits of each byte address are guaranteed to be 0, since all byte addresses in generated code are 32-bit aligned, therefore we can repurpose the low bit to indicate the indirect addressing mode
We manage this at the MIR level - we have for example LW, LH and LB MIR instructions that load (aligned) 32-bit words, 16-bit halfwords and 8-bit bytes from byte addresses that LLVM generates, respectively. LW is implemented as a simple assembly instruction (since we can load 32-bit words directly), whereas LH and LB are a lot more complicated since they need to load the whole 32 bit word and then compute individual bits depending on the subaddress within the word. But the end result is always that generated instructions reference only (32-bit aligned) byte addresses.
So this means:
- that the VM has to divide those byte addresses by 4 to obtain word addresses (i.e. indexes into our 32-bit word memory)
- the bottom two bits of each byte address are guaranteed to be 0, since all byte addresses in generated code are 32-bit aligned, therefore we can repurpose the low bit to indicate the indirect addressing mode
Hope this helps!