Re: Calling conventions -- easier way?
At 11:00 PM 10/19/2001 -0400, Bryan C. Warnock wrote: >On Friday 19 October 2001 01:46 pm, Dan Sugalski wrote: > > I'm currently leaning either towards returning values in registers > > [PSIN][0-4] with the total number of each type in register I0 somehow > >Order determination of the return values. That's an issue if we don't have declared return value lists. If we do, we can do it implicitly--the first five string returns are in S0-S4, the first four integers in I1-I4, the first five PMCs in P0-P4, and the first five floats in N0-N4. Without return value lists, I think we're going to have to either push 'em on a stack, or return a single list PMC with the returns. The only problem with a list is that you can only put PMCs in 'em, which won't work too well for those cases when you don't need a full PMC. Dan --"it's like this"--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Calling conventions -- easier way?
On Friday 19 October 2001 01:46 pm, Dan Sugalski wrote: > I'm currently leaning either towards returning values in registers > [PSIN][0-4] with the total number of each type in register I0 somehow Order determination of the return values. (Yes, I was the one asking for register windows. Shame on me.) -- Bryan C. Warnock [EMAIL PROTECTED]
Re: Calling conventions -- easier way?
Dan -- > Ah, but I'd rather do it right the first time than have to redo it later, > especially if the redoing is incompatible with what was done first. ;) I would, too. But I view Jako is being a sort of test bed for what our choices at the Parrot level do to language implementers. So, Jako is intended to track the current-best-practice, as it changes. That means I expect, for example, to re-implement the calling convention stuff a few times. Heck, Jako had subroutines before we had bsr! > >FWIW, I'd rather not dedicate registers to special uses at the Parrot > >level. > > These would only be reserved for subroutine calls, which is pretty standard > on CPUs with a reasonable number of registers. Normally a half-dozen or so > float and general registers are marked as scratch, so the callee can mess > with them as it wants. You say registers X-Y hold the parameters to the > caller, register X holds the return value, register Y holds the status (if > they're separate) and registers M-N are declared as scratch and the callee > doesn't have to preserve them. > > The only time these rules are in effect is when you make a sub call. Within > the sub, you can do whatever you like with the registers. > > Now, things are more interesting with Parrot, since we have at least one > language that can potentially take and return a huge list of things, which > is why I'm tending towards the "pass a list in P0, return a list in P0" way > of doing things, or a separate stack of values. The biggest problem with a > stack is that things are in reverse order, where passing in a list gets > them to you in proper order. I agree that a HLL that has a list type should use that list type for its arg and return passing. But, low level stuff (like Jako is currently) should still have access to a reasonable no-pmc-required calling convention, IMO. Regards, -- Gregor
Re: Calling conventions -- easier way?
At 01:55 PM 10/19/2001 -0400, Gregor N. Purdy wrote: >Dan -- > > > >Should we have bsr(i|ic, i|ic), that jumps to $1, with the return > > >address below the $2 arguments? Similarly, should we have ret(i|ic), > > >that rotates the return address out from under $1 arguments and then > > >returns to it? > > > > Nope. For a number of reasons, the biggest being that we're not returning > > our return values on the stack. :) > >Well, until something better comes along, Jako subroutines return *their* >return values on the stack... :) Ah, but I'd rather do it right the first time than have to redo it later, especially if the redoing is incompatible with what was done first. ;) > > > > OTOH, we could keep our current ABI, and pop the return address > into an I > > > > register, and then push it and ret, or jmp to it. > > > > > > The return address is a pointer, which doesn't necessarily fit in an > > > IV, > > > I believe. I played with doing this first, but didn't like having to > > > use > > > a register for it. If we wanted registers to be part of the calling > > > convention, we should just say so, but again we run into the question > > > of which type of register to use. > > > > I'm currently leaning either towards returning values in registers > > [PSIN][0-4] with the total number of each type in register I0 somehow, or > > as arg stack that's separate from the call stack. The latter is probably > > the better way to go, but it's got more overhead in some ways. It'd make > > interfacing with RPN languages easier, though. > >FWIW, I'd rather not dedicate registers to special uses at the Parrot >level. These would only be reserved for subroutine calls, which is pretty standard on CPUs with a reasonable number of registers. Normally a half-dozen or so float and general registers are marked as scratch, so the callee can mess with them as it wants. You say registers X-Y hold the parameters to the caller, register X holds the return value, register Y holds the status (if they're separate) and registers M-N are declared as scratch and the callee doesn't have to preserve them. The only time these rules are in effect is when you make a sub call. Within the sub, you can do whatever you like with the registers. Now, things are more interesting with Parrot, since we have at least one language that can potentially take and return a huge list of things, which is why I'm tending towards the "pass a list in P0, return a list in P0" way of doing things, or a separate stack of values. The biggest problem with a stack is that things are in reverse order, where passing in a list gets them to you in proper order. Dan --"it's like this"--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Calling conventions -- easier way?
On Fri, 19 Oct 2001, Gregor N. Purdy wrote: > Dan -- > FWIW, I'd rather not dedicate registers to special uses at the Parrot > level. Jako reserves [INPS]0 for temporaries, but that is at its > discretion, not dictated by Parrot (and I like it that way :). I was > wishing for separate data and address stacks when I was writing the > Jako calling convention stuff, but I can live with the rotate solution. > If the choices come down to reserved registers or separate stacks, > though, I'm squarely in the separate stacks camp. Not that it matters at this stage, but if we rely on compilers for temporaries, then what happens when we integrate different compiled binaries? MIPS (and I believe alpha) was good at reserved registers. Aside from "macro'd ops" most reserved registers only reserved at subroutine call time. Eventually all the compilers are going to have to deal with register renaming (we're going to run out of registers for a lot of code, and I don't think pushing and poping the register stack is going to be very helpful). I'd be curious to read up on register renaming compiler strategies (anybody have any online references?). Guess the basic algorithm is to assume an infinite number of registers, then perform data dependency checks and reduce the tree. In my up and comming post, I suggest a "peek R, i|ic" op-code which allows you to store fundamental datatypes in subroutine local stack memory (like hardware CPUs). If all variables are mapped within the stack frame, then register renaming should merely consist of pushing unused valued to their associated frame-offset and reusing that register and extracting it's replacement value from another address. -Michael
Re: Calling conventions -- easier way?
Dan -- > >Should we have bsr(i|ic, i|ic), that jumps to $1, with the return > >address below the $2 arguments? Similarly, should we have ret(i|ic), > >that rotates the return address out from under $1 arguments and then > >returns to it? > > Nope. For a number of reasons, the biggest being that we're not returning > our return values on the stack. :) Well, until something better comes along, Jako subroutines return *their* return values on the stack... :) > > > OTOH, we could keep our current ABI, and pop the return address into an I > > > register, and then push it and ret, or jmp to it. > > > > The return address is a pointer, which doesn't necessarily fit in an > > IV, > > I believe. I played with doing this first, but didn't like having to > > use > > a register for it. If we wanted registers to be part of the calling > > convention, we should just say so, but again we run into the question > > of which type of register to use. > > I'm currently leaning either towards returning values in registers > [PSIN][0-4] with the total number of each type in register I0 somehow, or > as arg stack that's separate from the call stack. The latter is probably > the better way to go, but it's got more overhead in some ways. It'd make > interfacing with RPN languages easier, though. FWIW, I'd rather not dedicate registers to special uses at the Parrot level. Jako reserves [INPS]0 for temporaries, but that is at its discretion, not dictated by Parrot (and I like it that way :). I was wishing for separate data and address stacks when I was writing the Jako calling convention stuff, but I can live with the rotate solution. If the choices come down to reserved registers or separate stacks, though, I'm squarely in the separate stacks camp. Regards, -- Gregor
Re: Calling conventions -- easier way?
On Fri, 19 Oct 2001, Dan Sugalski wrote: > At 01:24 PM 10/19/2001 -0400, Gregor N. Purdy wrote: > >James -- > > > >Should we have bsr(i|ic, i|ic), that jumps to $1, with the return > >address below the $2 arguments? Similarly, should we have ret(i|ic), > >that rotates the return address out from under $1 arguments and then > >returns to it? > > Nope. For a number of reasons, the biggest being that we're not returning > our return values on the stack. :) > > > > OTOH, we could keep our current ABI, and pop the return address into an I > > > register, and then push it and ret, or jmp to it. > > > >The return address is a pointer, which doesn't necessarily fit in an IV, > >I believe. I played with doing this first, but didn't like having to use > >a register for it. If we wanted registers to be part of the calling > >convention, we should just say so, but again we run into the question of > >which type of register to use. > > I'm currently leaning either towards returning values in registers > [PSIN][0-4] with the total number of each type in register I0 somehow, or > as arg stack that's separate from the call stack. The latter is probably > the better way to go, but it's got more overhead in some ways. It'd make > interfacing with RPN languages easier, though. > I was in the middle of writing up something on this topic.. I'm still working on the details, so I'll summarize. The more out-of-band data the better.. It's faster (no munging an all in one stack), more efficient (don't have to abstract it's type), and we're not limited like some hardware is (e.g. having a single stack segment). Most of my bias is based on a paper on stack-based machines presented by someone else earlier in this mailing list. It was a good paper, though somewhat dated. The only problem with having out-of-band return addresses is syncing up with the stack (unrolling it for exceptions of frame-analysis). I was working on a concept that used segregated stack-frames for the parameter stack, with the stack frame header referencing the "top-of-return-address stack". Alternatively, the return-address-stack could contain a reference into the parameter stack(s). The latter would be easier for unrolling, but makes the pushed value a little more complex. I'm not particular on the details, though I'm still working on them, but I definately think out-of-line return addresses are "good thing"(tm). -Michael
Re: Calling conventions -- easier way?
At 01:24 PM 10/19/2001 -0400, Gregor N. Purdy wrote: >James -- > > > Hey all. I just looked through the changes to jakoc, and I think the > > calling convention is mostly good... except for the return address. > > > > Originaly, I thought that perhaps it'd be good to put the return address > > after the args on the stack, so that once you've eaten the args, it's > in the > > right position to ret without doing any swaps. > >I just put in the 'rotate' op Dan requested instead of 'swap', and it begs >the question: > >Should we have bsr(i|ic, i|ic), that jumps to $1, with the return >address below the $2 arguments? Similarly, should we have ret(i|ic), >that rotates the return address out from under $1 arguments and then >returns to it? Nope. For a number of reasons, the biggest being that we're not returning our return values on the stack. :) > > OTOH, we could keep our current ABI, and pop the return address into an I > > register, and then push it and ret, or jmp to it. > >The return address is a pointer, which doesn't necessarily fit in an IV, >I believe. I played with doing this first, but didn't like having to use >a register for it. If we wanted registers to be part of the calling >convention, we should just say so, but again we run into the question of >which type of register to use. I'm currently leaning either towards returning values in registers [PSIN][0-4] with the total number of each type in register I0 somehow, or as arg stack that's separate from the call stack. The latter is probably the better way to go, but it's got more overhead in some ways. It'd make interfacing with RPN languages easier, though. Dan --"it's like this"--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Calling conventions -- easier way?
James -- > Hey all. I just looked through the changes to jakoc, and I think the > calling convention is mostly good... except for the return address. > > Originaly, I thought that perhaps it'd be good to put the return address > after the args on the stack, so that once you've eaten the args, it's in the > right position to ret without doing any swaps. I just put in the 'rotate' op Dan requested instead of 'swap', and it begs the question: Should we have bsr(i|ic, i|ic), that jumps to $1, with the return address below the $2 arguments? Similarly, should we have ret(i|ic), that rotates the return address out from under $1 arguments and then returns to it? These don't have to be instead of the exising ops. They can be in addition to them (since the current ops are equivalent to a final 0 arg in the new ones). > OTOH, we could keep our current ABI, and pop the return address into an I > register, and then push it and ret, or jmp to it. The return address is a pointer, which doesn't necessarily fit in an IV, I believe. I played with doing this first, but didn't like having to use a register for it. If we wanted registers to be part of the calling convention, we should just say so, but again we run into the question of which type of register to use. Regards, -- Gregor
Calling conventions -- easier way?
Hey all. I just looked through the changes to jakoc, and I think the calling convention is mostly good... except for the return address. Originaly, I thought that perhaps it'd be good to put the return address after the args on the stack, so that once you've eaten the args, it's in the right position to ret without doing any swaps. That would have to be done by doing a: SET In, *+ (Assuming that we can do constant arith on *) jmp OTOH, we could keep our current ABI, and pop the return address into an I register, and then push it and ret, or jmp to it. -=- James Mastros