Compiler code generation--register allocation inside conditional blocks - compiler-optimization

I'm writing a compiler for a course. I've run into some optimization issues of which I am unsure how to handle optimally. Suppose there is a while loop from the input language that uses N local variables which must be held in registers (or should be, for fast computations). Suppose N > K, the number of registers. There is a chance of the conditional register being changed near the end of the while loop.
For example, suppose the register for x (let's say %eax on i386) was determined before the following statement:
while ( x ) { x = x - 1 ; /* more statements */ }
In the more statements code, it is possible for x to be spilled back onto the stack. When the code jumps back to the beginning of the while loop to re-evaluate x, it will try to use %eax--but this may not even be holding the value of x now. So we could have something like
movl -8(%ebp), %eax # eax <- x
.... # do stuff but let x stay in %eax
_LOOP1: cmpl $0, %eax
....
movl -12(%ebp), %eax #eax now holds something else
....
jmp _LOOP1
One solution I'm using is to force the code to spill all modified registers before the while statement (so the registers are viewed as empty from the code generator's perspective). After the label for the while loop, the code has to load everything into a register as necessary.
My solution is something like this:
movl -8(%ebp), %eax # eax <- x
.... # do stuff but let x stay in %eax
movl %eax, -8(%ebp) # spilling and clearing all registers
_LOOP1: movl -8(%ebp), %eax # get a register for x again
cmpl $0, %eax
....
movl -12(%ebp), %eax # eax now holds something else
....
movl %eax, -8(%ebp) # spill to prevent overwrite
jmp _LOOP1
It seems like my solution is a little extraneous or unnecessary. Is there some general optimization trick I am forgetting here?
EDIT: I would also like to note something similar occurs for conditionals such as if and if else. This occurs for them because a register may be allocated for a variable inside the block for the conditional, but the code generator assumes it was moved in there for everything else after. I have almost the same approach for dealing with that case.

The general technique you're looking for here is usually called "live range splitting". A Google Search for that term will give you pointers to a bunch of different papers. Basically the idea is that you want to split a single variable (x in your example) into multiple variables with disjoint live ranges each of which gets copied to the next at the splitting point. So you'd have x.0 before the loop, which is copied into x.1 just before the while and used as that in the loop. Then right after the loop, you'd copy x.1 into x.2 and use that after the loop. Each of the split vars would be potentially allocated to a different register (or stack slot).
There are a lot of tradeoffs here -- too much splitting leads to (many) more variables in the code, making register allocation much slower, and potentially leading to unnecessary copies.

Related

Dosbox error A2053: Jump out of range 60 bytes

It says that Jump out of range by 60 bytes
To solve my problem.
Conditional jumps in 8086 Assembly (and most assembly languages) have a limited distance they can jump. In other words, there's too much code between your jump instruction and the destination (in this case, 60 bytes too many). You didn't post your code so I can't tell you exactly what line to fix, but in general the solution is straightforward.
cmp ax,bx
jnz goHere
; more code is here than the conditional jump will allow
goHere:
; finish up what we were doing
ret
In order to fix the above code, we have to reverse the condition and JMP, since JMP isn't as limited as Jxx is.
cmp ax,bx
jz continue:
jmp goHere
continue:
; finish up what we were doing
ret
goHere:
; now we can get here even though we have too much code for a conditional jump
jmp continue ;this will also have enough range to go there.
There's several ways to re-arrange your code to allow conditional jumps to work as intended, and still get the desired outcome. This is just one technique for it.

Windows 10 IDA freeware 64bit cannot find main

I coded a C program in vistual studio and complied in 64 bit
#include<stdio.h>
int main()
{
printf("Hello World!!!\n");
return 0;
}
And I use IDA freeware to disassembly it, I didn't see main but follow
public start
start proc near
jmp start_0
start endp
after I clicked start_0, The following code showed
start_0 proc near
arg_0= qword ptr 8
mov [rsp+arg_0], rcx
sub rsp, 28h
call sub_7FF691D52000
add rsp, 28h
retn
start_0 endp
obviously not main too, and I also didn't find main in function table and also I found a answer in the internet
Windows --> Exports
But I only saw start function in the result
how to find main? where to find it? or do I need to set somethings?
To find functions by name used in sources, you can load your programs symbols in IDA (pdb file).
Without symbols you can open strings view, find there "Hello World!!!\n" string and double-click it.
IDA View opens with the cursor on the strings address. Open XREFS window (Ctrl+X) of this string. It should contain only one entry - your printf function.
Double-click this entry and you will land on printf in your main.

How can I evaluate an expression in IDA Pro?

I want to evaluate an expression on IDA Pro. Look at this code:
mov rex, [rbp + var_XYZ]
If I put my cursor on [rbp + var_XYZ], it will show me the value of the address and content, but I would like to see individually rbp value and var_XYZ.
I also want to change values of var_XYZ. I have tried a lot of things.
Thanks

How can I continue after a breakpoint in windbg?

I have set a breakpoint which should print a pointer and then continue, because I don't want to stop there.
bu 410cc8 ".printf \"Class: %08lX Filebuffer: %08X\\n\", eax, edx; g"
The problem with this is now, when I singlestep and such a breakpoint is fired, like here:
1 mov eax, [ebp+var_10]
2 lea edx, [eax+2Ch]
3 mov eax, ebx
4 call ReadFileFkt_2
5 mov eax, [ebp+var_10]
So when I'm on line 4, and step over it, the above breakpoint is fired and the message is printed. But then the debugger never comes back, because in the breakpoint I use "g" to continue, so the single step is erased.
If I don't use "g" then the breakpoint will be hit and the debugger stops there, so I have to track my way back to where I came from. Of course I could set a breakpoint after the call, but then I would have to remember doing this in other parts of the code as well, because I don't know when the breakpoint is fired from deep within some calling hierarchy.
Use 'gc' (go from conditional breakpoint) instead of 'g' (go).
This command was designed specifically for the problem you have.

Xcode project always throws SIGTRAP?

This might be a somewhat obscure or project specific question, but my project is throwing a SIGTRAP for every exception that is encountered. I've never seen this before, and now it is throwing it every time there is a problem with my code and it does nothing to help me debug it. In my other class that is similar I will get an index out of bounds exception, but in this class it's just SIGTRAP and I have to turn on exception breakpoints to see where the error is. I'm not good with debugging this kind of thing, but here's some of the info that is presented, let me know if anything else would be helpful.
libsystem_kernel.dylib`__kill:
0x96f283b0: movl $786469, %eax
0x96f283b5: calll 0x96f2a4c2 ; _sysenter_trap
0x96f283ba: jae 0x96f283ca ; __kill + 26
0x96f283bc: calll 0x96f283c1 ; __kill + 17
0x96f283c1: popl %edx
0x96f283c2: movl 27739(%edx), %edx
0x96f283c8: jmpl *%edx
0x96f283ca: ret
0x96f283cb: nop
Thanks for your help.
Error shows that you are accessing index which is not accessible.
You must have problem in your loop,check conditions and loops and clean the project..
Good Luck !!