digitalmars.D - Call Conventions
- Dan (14/14) Jan 03 2008 While I must admit it's most probably a very rare thing to need to speci...
- Jason House (3/34) Jan 03 2008 That sounds like a coll feature that D should have. I have no idea how ...
- Dan (25/43) Jan 03 2008 ...
- Alan Knowles (40/68) Jan 04 2008 While it's not going to solve that issue, I think this should achieve
- Dan (14/16) Jan 04 2008 Unfortunately, no, that's quite a ways off the mark from what I'm trying...
- Dan (2/2) Jan 04 2008 PS: This is how Watcom C/C++ did it:
- Simen Kjaeraas (8/29) Jan 13 2008 g =
- Daniel Lewis (4/19) Jan 13 2008 Yeah, I'm absolutely horrible with templates, and I have no idea what th...
While I must admit it's most probably a very rare thing to need to specify a calling convention; when you do need to it's excrutiating. For Walnut, I'm currently doing this: struct Value.sizeof = 16; Value x(Value self, Value cc, Value[] arguments ...){ bla bla bla } Now, the way that's getting done by D is absolutely horrid compared to the way I'd like to do it - by taking advantage of XMM registers, using the functions to mutate self, cc, and a third variable which keeps getting returned, while arguments get copied. I don't understand how I can do that in D without declaring every single function naked, templating in raw assembler, and then processing the function using raw assembler because the variables aren't where D expects. *sigh* How about a way to specify call convention and use it via extern(MyCallConvention) Would be fabulous. Regards, Dan
Jan 03 2008
Dan wrote:While I must admit it's most probably a very rare thing to need to specify a calling convention; when you do need to it's excrutiating. For Walnut, I'm currently doing this: struct Value.sizeof = 16; Value x(Value self, Value cc, Value[] arguments ...){ bla bla bla } Now, the way that's getting done by D is absolutely horrid compared to the way I'd like to do it - by taking advantage of XMM registers, using the functions to mutate self, cc, and a third variable which keeps getting returned, while arguments get copied. I don't understand how I can do that in D without declaring every single function naked, templating in raw assembler, and then processing the function using raw assembler because the variables aren't where D expects. *sigh* How about a way to specify call convention and use it via extern(MyCallConvention) Would be fabulous. Regards, DanThat sounds like a coll feature that D should have. I have no idea how it'd get implemented under the hood.
Jan 03 2008
Jason House Wrote:Dan Wrote:......Now, the way that's getting done by D is absolutely horrid compared to the way I'd like to do it - by taking advantage of XMM registers, using the functions to mutate self, cc, and a third variable which keeps getting returned, while arguments get copied. I don't understand how I can do that in D without declaring every single function naked, templating in raw assembler, and then processing the function using raw assembler because the variables aren't where D expects. *sigh* How about a way to specify call convention and use it via extern(MyCallConvention)That sounds like a coll feature that D should have. I have no idea how it'd get implemented under the hood.Well, I would suggest utilizing opCall for the caller side... The idea is that if you inline opCall(), then essentially the code being generated is the contents of it (which could be inline assembler, or whatever works) The real problem comes in the callee side, because you need to run arbitrary code before what you see (typically the ebp/esp stuff), bind registers and/or stack variables to names correctly, and then run arbitrary code after what you see (closing the context by add ebp or whatever) My first suggestion would be that one could probably declare a given function to be a convention, at which point, any functions declared with that convention are passed as delegates to it. extern(MyConvention) = MyConventionFunction; void MyConventionFunction(lazy function f, *whatever*) { bla bla bla f(); bla bla bla } extern(MyConvention) void bob() { bla bla bla // this gets wrapped according to MyConventionFunction } Beyond that, using inline assembler correctly should handle the rest; and anyone who can't do that probably shouldn't be writing a call convention. Is that correct enough? How hard would it be to do that? Is it possible to achieve this with mixins/templates without needing to butcher the "void bob(){}" functions? (there'll be hundreds, and they *should* be legible) Regards, Dan
Jan 03 2008
While it's not going to solve that issue, I think this should achieve what you are trying to do, although not quite as clean... import std.string; import std.stdio; class Value { static Value[] emptyAr; int type = 0; int ival; this(int v) { this.type = 1; this.ival = v; } char[] cval; this(char[] v) { this.type = 2; this.cval = v; } char[] asString() { if (this.type == 2){ return cval; } return std.string.toString(ival); } } void testArgs(char[] x, Value[] somevals) { foreach (v; somevals) { writefln("got vals %s", v.asString()); } } void main () { testArgs("fred", Value.emptyAr ~ (new Value(3)) ~ (new Value("dog")) ~ (new Value(6))); } Dan wrote:While I must admit it's most probably a very rare thing to need to specify a calling convention; when you do need to it's excrutiating. For Walnut, I'm currently doing this: struct Value.sizeof = 16; Value x(Value self, Value cc, Value[] arguments ...){ bla bla bla } Now, the way that's getting done by D is absolutely horrid compared to the way I'd like to do it - by taking advantage of XMM registers, using the functions to mutate self, cc, and a third variable which keeps getting returned, while arguments get copied. I don't understand how I can do that in D without declaring every single function naked, templating in raw assembler, and then processing the function using raw assembler because the variables aren't where D expects. *sigh* How about a way to specify call convention and use it via extern(MyCallConvention) Would be fabulous. Regards, Dan
Jan 04 2008
Alan Knowles Wrote:While it's not going to solve that issue, I think this should achieve what you are trying to do, although not quite as clean...Unfortunately, no, that's quite a ways off the mark from what I'm trying to do. I was hoping to change how the program internally handles function calls. For example; if we use "extern(C)", - all the arguments are pushed onto the stack from right to left - return value is in eax or fp0 - cleanup is by the caller. So when we go: extern(C) int main(char[][] arguments), the caller knows to get the result from eax, and to push twice to make a D array, and to add 4 to esp afterwards to clean up. the callee knows that if there are any local variables, it needs to wiggle ebp and esp to cause the local variables to get wiped when the function returns. That's _cdecl. There's also syscall, optlink, pascal, fastcall, stdcall, safecall, and thiscall amongst the ones listed on wikipedia: http://en.wikipedia.org/wiki/X86_calling_conventions I was hoping to roll my own which allowed me to pass Value structs by SSE2 registers. Perhaps that's a little optimistic, but that's what got me thinking about this.
Jan 04 2008
PS: This is how Watcom C/C++ did it: http://www.openwatcom.org/index.php/Calling_Conventions#Specifying_Calling_Conventions_the_Watcom_Way
Jan 04 2008
Dan <murpsoft hotmail.com> wrote:While I must admit it's most probably a very rare thing to need to =specify a calling convention; when you do need to it's excrutiating. For Walnut, I'm currently doing this: struct Value.sizeof =3D 16; Value x(Value self, Value cc, Value[] arguments ...){ bla bla bla } Now, the way that's getting done by D is absolutely horrid compared to==the way I'd like to do it - by taking advantage of XMM registers, usin=g =the functions to mutate self, cc, and a third variable which keeps =getting returned, while arguments get copied. I don't understand how I can do that in D without declaring every sing=le =function naked, templating in raw assembler, and then processing the =function using raw assembler because the variables aren't where D =expects. *sigh* How about a way to specify call convention and use it via extern(MyCallConvention) Would be fabulous. Regards, DanI'm sure if we could get downs or Don to work on this, it could be done = = via some funky template mixin - possibly with absurd syntax (downs). Simen Kjaeraas
Jan 13 2008
Simen Kjaeraas Wrote:Dan <murpsoft hotmail.com> wrote:Yeah, I'm absolutely horrible with templates, and I have no idea what the final executable is actually like inside; there are 80kb of "library/gc crap" that come with every executable that I can't see past enough to be able to profile. I tried extracting the GC out to a DLL, but nobody seems to know how to, apart from "it's possible" and "you can make DLL's use the EXE's GC doing this and this and this." Consider I can't just do it, maybe I'm not all the programmer I like to make myself out to be.How about a way to specify call convention and use it via extern(MyCallConvention) Would be fabulous. Regards, DanI'm sure if we could get downs or Don to work on this, it could be done via some funky template mixin - possibly with absurd syntax (downs). Simen Kjaeraas
Jan 13 2008