How does expressions work in one pass compiler? - parsing

I have seen a lot of posts regarding one pass and multi pass compilers and I think the basic parts of a One Pass Compiler as follows.
Lexical Analysis
Parse and Syntax Check
Symbol Table
Code Generation
But I have a question, that I cannot understand. How does Expression work in one pass compiler ( Without AST )
Let's take 1 + 2 / 3 as an example. Suppose you need to generate assembly code for this. After create a parser, how does generate assembly from it? ( Directly ) How does assembly code generate without any errors?
Can you explain this with examples? Please tell me if there is a problem in this question. I am new to Stackoverflow :)

The simplest way for a single-shot compiler process something like a=b*c[i]+d*e; would be to process each token as it is encountered:
a Generate code to push the address of a onto the stack
= Record the fact that the top item on the stack will be used as the target of an assignment.
b Generate code to push the address of b onto the stack
* Generate code to pop the address (of b), fetch the object there, and push it.
Also record the fact that the top item on the stack will be used as the left operand of a multiply.
c Generate code to push the address of c onto the stack
[ Record the fact that the top item on the stack will be the left operand of [ and evaluate the following expression
i Generate code to push the address of i onto the stack
] Generate code to pop the address (of i), fetch the object there, and push it.
Also pop the two items on the stack (the value of i and the address of c, add them, and push that result
+ Generate code to pop the address (of c[i]), fetch the object there, and push it
Also generate code to pop the top two values (c[i] and b), multiply them, and push the result
Also record the fact that the top item on the stack will be the left operand of +
d Generate code to push the address of d onto the stack
* Generate code to pop the address, fetch the object there, and push it.
Also record the fact that the top item on the stack will be used as the left operand of a multiply.
e Generate code to push the address of e onto the stack
(end of statement): Generate code to pop the address (of e), fetch the object there, and push it
Also generate code to pop the top two values (e and d), multiply them, and push the result
Also generate code to pop the top two values (d*e and b*c[i]), add them, and push the result
Also generate code to pop a value (b*c[i]+d*e) and address a and store the value to the address
Note that on many platform, performance may be enormously improved if code generation for operations which end with a push is deferred until the next operation is generated, and if pops that immediately follow pushes are consolidated with them; further, it may be useful to have the compiler record the fact that the left hand side of the assignment operator is a, rather than generating code to push that address, and then have the assignment operator perform a store directly to a rather that computing the address first and then using it for the store. On the other hand, the approach as described will be able to generate machine code for everything up to the exact byte of machine code being processed, without having to keep track of much beyond pending operations that will need to be unwound.

Related

How does Assembly Work with Stack Correctly

I always have a question about how to calculate the stretch of the stack. For example, when I have more than 8 parameters in arm64, he actually uses the area of my previous function call stack. After BL enters the function, he uses SP to add back to get the parameters, which is equivalent to crossing a stack. How can he avoid polluting the previous stack in this case? Thank you for your answer
You are correct: the function arguments which do not fit in registers will be pushed onto the stack before calling your function. Therefore, they will be at addresses with positive offsets from SP on entry to your function, and I can see why you might be concerned that it is not safe to access this memory. However, this memory is in fact "yours".
The ARM Procedure Call Standard section 6.4.2 states "A callee is permitted to modify any stack space used for receiving parameter values from the caller". So, there is no need to worry. The caller is expecting you to access this memory, and even to modify it if you want, and nothing will break if you do.

What does 'return from subroutine' mean?

I'm trying to build my first ever CHIP-8 emulator from scratch using C. While writing necessary code for the instructions, I came across this opcode:
00EE - RET
Return from a subroutine.
The interpreter sets the program counter to the address at the top of the stack, then subtracts 1 from the stack pointer.
(http://devernay.free.fr/hacks/chip8/C8TECH10.HTM)
I know that a subroutine is basically a function, but what does it mean to 'return' from a subroutine? And what is happening to the program counter, stack, and the stack pointer respectively?
(One additional question): If I created an array that can hold 16 values to represent the stack, will the 'top of the stack' be STACK[0] or STACK[15]? And where should my stack pointer be?
To return from a subroutine is to return code execution to the point it was at before the subroutine was called.
Therefore, given that calling a subroutine pushes the current address PC+2 (+2 to jump past the call instruction) onto the stack. Returning from a subroutine will return execution to the address that was pushed to the stack by popping the address from the stack. (e.g. pc=stack[sp]; sp-=2;)
As for the additional question, it really depends on whether you define your stack as being ascending or descending. For the CHIP-8 the choice is not specified.

Implementing Stack Layout in LLVM Backend

I'm trying to implement a Backend for LLVM.
Right now I'm running into problems with stack frame lowering.
I need to implement the following stack layout:
When a function gets called I need to put a "Return Symbol"(as the target system can only jump to absolute adresses) and "Offset" onto the stack followed by all the function arguments.
The stack alignement is 1 Byte and the stack has to grow up.
Stack Layout before Call:
RetSymb <- SP
Offset
Arguments
Local Data
Stack Layout before entry to function:
RetSymb
Offset
Arguments
Local Data
RetSymb <- SP
Offset = SP - Old SP
Arguments
Local Data
On return the SP gets automatically decremented by the value stored in "Offset".
Variable argument handling is not an importance right now.
I currently have no idea at which places I have to look and what I need to do at those places.
I have found the emitPrologue and emitEpilogue functions in the XXXFrameLowering.cpp but I don't really know what they are supposed to do (I guess insert code at start and end of a function).
I also found a couple of functions in the XXXISelLowering.cpp file. Is there a List that explains what the different functions are supposed to do?
For example:
LowerFormalArguments(I guess insert load from stack for arguments)
LowerCallResult
LowerCall
LowerReturn
Thanks in advance for any information that point me in the right direction.
To the best of my knowledge, there's no single place that explains this. You'll have to pick one of the existing backends and follow its code to see where the magic is done. emitPrologue and emitEpilogue are good candidates to start from, because these specifically deal with the code that sets up and tears down the frame in a function. A function is lowered to (rough approximation, there are more details...):
func_label:
prologue
.. function code
epilogue
So to handle the custom stack layout you will definitely have to write custom code for the prologue and epilogue. The same goes for calls to functions, if the caller is responsible for some of the stack layout.
I suggest you begin by reading about the stack frame layout of some of the existing backends and then study the relevant code in LLVM. I described some of the x86 (32-bit) frame information here, for example.

PDA to accept a language of strings containing more a's than b's

Produce a PDA to recognise the following language : the language of strings containing more a's than b's
I have been struggling with this question for several days now, I seem to have hit a complete mental block. Would any one be able to provide some guidance or direction to how I can solve this problem?
Your problem of "more a's than b's" can be solved by PDA.
All you have to do is:
When input is a and the stack is either empty or has an a on the top, push a on the stack; pop b, if b is the top.
When input is b and the stack is either empty or has an b on the top, push b on the stack; pop a, if a is on the top.
Finally, when the string is finished, go to the final state with null input if a is on top of the stack. Otherwise you don't have more a's than b's.
I have come up with a more general solution to the problem concerning the number of as and bs, see the picture below:
where a > b means more as than bs and so does a < b , a = b.
Z means the bottom of stack, and A/B are stack symbols.
I'm excited about it because this PDA seperates the 3 different states. In your problem, you can just set the a > b state to be the final state and let a = b be the start state.
And if you want to step further, you can use this PDA to easily generate PDAs for a >= b, a - b >= 1, 2 <= a - b <= 3 etc, which is fascinating.
I'm assuming you mean strings of the form a^nb^m, where n>m.
The idea is relatively easy, for a you push it on the stack (in a loop), for b you switch to a separate loop to pop a from the stack. If the stack is ever empty, you give up with a FAIL. If in the first loop you get anything other than a or b, or in the second loop you get anything other than b, you give up with FAIL.
At the end you try to pop another a and if the stack is empty you give up with a FAIL (ie, you had at least as many b's as a's on the stack, possibly more). If not, SUCCESS.
Edit: As a side note, I'm not convinced this is the right site for this question, might be better on programmers. Not sure though so not voting to close.
PDA to accept more a's than b's
Basic infromation of transaction is given in below figure.
Here is the complete transaction.
In it є is equal to NULL.
$ sign is pushed into stack at the start of the string and pop at the end to determine the string has been completely read and end now. qo is start state and q5 is final state
It is Non-deterministic push down Automata (NPDA).So Due to NPDA the transaction of rejection string is not shown in it.

Reflection.Emit Opcode for peeking at the stack?

Is there a way to look up into the stack via Reflection.Emit Opcodes? For example, let's say I want to push X, and then push Y, and then I need to get at the value of X...how do I go about that?
True, I could store y into a local variable, and then later load Y again, but that's a bit of a round-about way of going at it.
There is no direct way to do this. See Reflection.Emit - access topmost-but-one item from stack for another related question.

Resources