[M3devel] front end function about a "virtual stack"
Jay K
jay.krell at cornell.edu
Sun Feb 7 08:02:24 CET 2010
I think I have this aspect dealt with now.
Convert.m3:
-----LINE 129 -----
load tv.25[_nDigits] 0 Int.32 Int.32
check_range 0 n:8,x:0,0,0,0,0,0,0,0 64 n:4,x:40,0,0,0,0,0,0,0 2
00000435: 8B5DFC MOV EBX tv.25[_nDigits]
00000438: 83FB40 CMP EBX $64
0000043B: 7600 JBE rel8 L.68
0000043D: B822100000 MOV EAX $4130
00000442: E800000000 CALL L.0
loophole Int.32 Int.32
load_address tv.31[_result] 0
00000447: 8D75AE LEA ESI tv.31[_result]
swap Int.32 Addr
index_address Int.32 1
0000044A: 03F3 ADD ESI EBX ** result location in ESI *
load tv.35[_base] 0 Word.8 Int.32
loophole Int.32 Int.64
0000044C: 33D2 XOR EDX EDX
0000044E: 8A5514 MOV EDX tv.35[_base]:Word.8
00000451: 33FF XOR EDI EDI
load tv.34[_value] 0 Int.64 Int.64
swap Int.64 Int.64
mod Int.64 X P
call_64 m3_mod64 2
import_procedure m3_mod64 2 Int.64 "__stdcall" p.31[m3_mod64]
declare_param * 8 8 Word.64 0 F F 100 tv.201[T$201] 8
declare_param * 8 8 Word.64 0 F F 100 tv.202[T$202] 16
start_call_direct p.31[_m3_mod64 at 16] 0 Int.64
load_stack_param Word.64 1
00000453: 8B4D0C MOV ECX tv.34[_value]
00000456: 8B4510 MOV EAX tv.34[_value]+4
00000459: 50 PUSH EAX
0000045A: 51 PUSH ECX
load_stack_param Word.64 0
0000045B: 57 PUSH EDI
0000045C: 52 PUSH EDX
declare_temp 4 4 Addr F tv.203[T$203] -92
0000045D: 8975A4 MOV tv.203[T$203] ESI ** ESI saved unnecessarily in temporary to satisfy us **
call_direct p.31[_m3_mod64 at 16] Int.64
00000460: FF1500000000 CALL p.31[_m3_mod64 at 16]
loophole Int.64 Int.32
loophole Int.32 Int.32
load_address gv.2[_MM_Convert] 52
00000466: 8D3534000000 LEA ESI gv.2[_MM_Convert]+52
swap Int.32 Addr
index_address Int.32 1
0000046C: 03F0 ADD ESI EAX
load_indirect 0 Word.8 Int.32
0000046E: 33DB XOR EBX EBX
00000470: 8A5E00 MOV EBX ESI^[0:Word.8]
store_indirect 0 Int.32 Word.8
00000473: 8B75A4 MOV ESI tv.203[T$203]:Addr ** ESI refetched from temporary **
free_temp tv.203[T$203]
00000476: 885E00 MOV ESI^[0:Word.8] EBX
-----LINE 130 -----
Pretty wasteful.
Instead it should just compute the destination when it does the store.
- Jay
From: jay.krell at cornell.edu
To: hosking at cs.purdue.edu
CC: m3devel at elegosoft.com
Subject: RE: front end function about a "virtual stack"
Date: Sun, 7 Feb 2010 06:49:11 +0000
> But, there have always been calls for mod/div
Not on NT386.
- Jay
Subject: Re: front end function about a "virtual stack"
From: hosking at cs.purdue.edu
Date: Sat, 6 Feb 2010 13:07:23 -0500
CC: m3devel at elegosoft.com
To: jay.krell at cornell.edu
The front-end does do that for known calls. But not for arithmetic ops. You will need to cope in the backend. But, there have always been calls for mod/div, so I think it really comes down to the back-end needing to do the right thing.
On 6 Feb 2010, at 07:29, Jay K wrote:
Tony, can you confirm something?
It's hard to explain.
The NT36 backend of course maintains
a bunch of information as to which registers are in use.
For example, at the start of the function, it
marks all registers as not in use.
(It always preserves all volatile registers I believe.
Obviously it could do better. It should only
mark non-volatile registers as in use, see
which registers it uses in the function, and
then only preserve/restore the nonvolatile ones
that it uses.)
As well when it generates a function call it
marks them as all not in use too.
But in that case, it checks itself.
Again, it is a bit dumb -- nonvolatile registers
would be ok to still be in use.
Now, all is ok.
But then, I've introduced function calls where
they weren't before -- multiply, divide, mod etc.
Upon generating the call to mod (for example),
I get an assertion failure, because registers
are still in use. In this case it is a nonvolatile
register, but I think that's largely luck.
In particular I think the location that
will be stored to after the mod is in a register.
That is reasonable.
You know..as a compiler, given:
*(a + b) = f();
you might generate code to evaluate a + b first,
put it in a (non volatile) register, then call f(),
or you might call f() first.
A simpler approach is to call all the functions first,
so you have more easy use of registers.
But then imagine
*(a + b) = (c % d);
is there a function call in there or not?
It depends.
So then my question is, like, when does the
frontend assume a "stack based code generator"'s
stack can/should/will be empty?
Does it endeavor to make it so?
That is, is it very reasonable to for the NT386
backend to assume its stack is empty when
it calls a function, because the front end
colludes to make it so, but then
the front end doesn't do similar for things
like multiply/divide?
I can deal with this pretty easily either way.
Around function calls I introduce that weren't
previously there I can save whatever volatile
registers are in use.
But I'd like to understand.
Thanks,
- Jay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20100207/ab5b328f/attachment-0002.html>
More information about the M3devel
mailing list