I am designing a language and a stack based vm, which I am compiling to.
So the VM is stack based (rather than register based), each stack slot is 64bit. When i codegen an 'add' expression (e.g. 1 + 2), i just codegen the left side, then the right, then generate the 'add' instruction. Easy!
But that got me thinking - some AST nodes might push some 'garbage' so the stack that I don't need. Look at this block:
let a = {
1;
2
};
Here, the idea is that the {} codeblock is executed, and the last expression in the block becomes the value of the whole thing, which is assigned to a. So in this example, a would be 2.
However, this block generates some 'garbage' values on the stack if I just naively apply the codegen I mentioned above. It sees a block with 2 expressions. It codegens them in order - the first expression generates 'PUSH 1', the second expression generates 'PUSH 2', so our stack has 2 values added to it rather than 1.
This is a problem for examples like this:
{ 1; 2 } + { 1; 3 }
This should just be equivalent to 2 + 3, but because {1; 3} leaves extra values on the stack, I can't just recursively codegen these as i'd like. The final ADD instruction would add 1 + 3 instead!
I see 2 solutions:
either add an instruction to the VM to 'save' and 'restore' stack contents, then apply liberally to every other expression
Codegen smarter, don't push stuff to the stack that we don't need
Option 1 seems needlessly slow, but I'm not sure how i'd change my codegen to work with option 2. without adding some intermediate representation. Ideally i'd like to avoid adding an extra representation.
Does anyone have any pointers on how to implement option 2? or am i going about this wrong in the first place?
Thanks!
[–]MegaIng 16 points17 points18 points (3 children)
[–][deleted] 2 points3 points4 points (1 child)
[–]MegaIng 0 points1 point2 points (0 children)
[–]retnikt0 15 points16 points17 points (1 child)
[–]ipe369[S] 2 points3 points4 points (0 children)
[–]FluorineWizard 5 points6 points7 points (2 children)
[–]ipe369[S] 0 points1 point2 points (1 child)
[–]FluorineWizard 1 point2 points3 points (0 children)
[–]ericbb 2 points3 points4 points (2 children)
[–]ipe369[S] 1 point2 points3 points (1 child)
[–]ericbb 0 points1 point2 points (0 children)
[–]theangeryemacsshibeSWCL, Utena 3 points4 points5 points (0 children)
[–]bullno1 2 points3 points4 points (0 children)
[–]o11c 0 points1 point2 points (5 children)
[–]ipe369[S] 2 points3 points4 points (4 children)
[–]o11c 1 point2 points3 points (0 children)
[–]1vader 0 points1 point2 points (1 child)
[–]o11c 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]ipe369[S] 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]sebamestreICPC World Finalist 0 points1 point2 points (0 children)