0

I'm writing a bytecode compiler and a VM. I'm able to use constants by placing any non-integer values in a constant pool and pushing the 4-byte integer address on to the stack. That part is fine.

But now I'm adding global variables which get stored in a virtual memory area which I call "Ram". The values I store there will, of course, also be indexed by address just like the constants. So let's say I push two addresses on to operand stack and then run my FADD (Floating Add) - when the instruction pops the two addresses off the stack to perform the addition, how does it know if those addresses come from the global memory as opposed to the constant pool? What is the standard approach?

JackP
  • 119
  • 3

1 Answers1

2

FADD shouldn't be popping addresses of the stack, it should be popping values.

You should have instructions for constants and for reading memory. Those instructions should push the resulting value onto the stack - not the index in the constant table or an address. The index of a constant should never be pushed onto the stack - the value of the constant itself should.

FADD should then simply pop two values from the stack and add them - it shouldn't need to look up anything in the constant table or in memory because that should already have been handled by instructions dedicated to that.

For example, given the constant table [0: 1.0, 1: 0x10], the instructions for adding 1.0 to whichever value is stored at the address 0x10 (let's say 4.2) could look like this (assuming CONST instructions that push the value at the given index in the constant table onto the stack and LOAD instructions that pops an address of the stack and push the value at that address onto the stack):

FCONST 0  // Stack: [1.0]
ICONST 1  // Stack: [1.0, 0x10]
FLOAD     // Stack: [1.0, 4.2]
FADD      // Stack: [5.2]
sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • That clears it up ..! Thanks a million. I just have a quick follow up question, though. In your example, I have an integer constant and then a float in the stack. I'm assuming that what I'm actually storing in each stack element are the bytes for INT and FLOAT which I then need to convert to their respective values (1.0 and 4.2) before adding them. When I go to FADD, how does the code for adding I know to convert the lvalue to INT and the other to FLOAT after popping them off the stack? – JackP Jul 23 '19 at 08:10
  • @JackP That depends. If all your types have the same size or you're okay with wasting some bytes, you can use a union as the element type of the stack (or you use the largest type and bitcast it to the appropriate type when needed). Otherwise you could use a stack of bytes and push and pop only the necessary amount of bytes for a given type and then bitcast those bytes. If your VM is dynamically typed, you'd store both the data and something that tells you what the type is. That could take the form of a tagged union or a subclass hierarchy. – sepp2k Jul 23 '19 at 09:32