D - What's the Current & Future Status of Functoin Pointers?
- Russell Lewis (18/18) Jan 22 2003 I know that delegates are in. C-style function pointers still work as
- Walter (6/10) Jan 25 2003 Daniel and I have talked about a unified syntax for delegates and functi...
- Russ Lewis (15/25) Jan 27 2003 The parser project started a long time ago. As it turned out, I've writ...
- Bill Cox (8/48) Jan 27 2003 Hi, Russ.
- Russ Lewis (22/27) Jan 27 2003 Unfortunately, the company I work for is really strict about intellectua...
- Ilya Minkov (13/25) Jan 27 2003 Good.
- Ilya Minkov (21/32) Jan 27 2003 Hello.
- Garen Parham (18/24) Jan 30 2003 GCC isn't poorly designed as far as I can tell; it is slow as hell thoug...
- Mike Wynn (53/77) Jan 30 2003 Have I missed something here, but who cares how fast/slow the compiler i...
- Garen Parham (16/52) Jan 30 2003 Code generation is more important, but compile time performance is very
- Mike Wynn (16/21) Jan 30 2003 people were complaining that gcc is slow becasue it has gc (garbage
- Ilya Minkov (11/25) Jan 30 2003 My main development computer is a notebook, Pentium MMX 233 MHz, 64 MB,
- Ilya Minkov (46/62) Jan 30 2003 Does it do GC? Then why does it swap like hell on my 64mb notebook
- Garen Parham (11/32) Feb 01 2003 Yeah, GCC uses the boehm GC. C and C++ supposedly aren't very
- Ilya Minkov (13/19) Feb 01 2003 Eliminating intermediate structures speeds up compilation immensely, but...
- Burton Radons (21/24) Jan 27 2003 I agree, the current function pointer syntax is weird; nontrivial usages...
- Burton Radons (22/29) Jan 27 2003 Wait, that's not right; the real function will still have four bytes too...
- Scott Wood (9/12) Jan 27 2003 Though, the spec says that COM functions already need to use
- Russ Lewis (8/12) Jan 27 2003 You could do that, except that we would need some syntax for interfacing...
- Burton Radons (8/18) Jan 27 2003 Yeah, I think removing them wouldn't work; any method I can think of for...
- Scott Wood (11/23) Jan 27 2003 What about modifying the ABI so that "this" is the last argument,
I know that delegates are in. C-style function pointers still work as well (in DLI, at least). Is there any plan for delegate-style syntax of extern(C) function pointers? The problem I'm facing is that I'm writing a parser for D. It's pretty trivial to write a grammar rule for a function declaration: function_declaration: type IDENT ( type IDENT , ... ) { statement ... } It's clean, sensible, and easy to read. But if I have to support old-syntax C function pointers, then things get REALLY REALLY ugly! Now, the type is spread out, partially in front of the IDENT and partially after it. So the grammar gets really hard to read: function_declaration: type IDENT ( func_decl_arg , ... ) { statement ... } func_decl_arg: type IDENT type ( * IDENT ) ( func_decl_arg , ... ) However, if we could use something like the delegate syntax for EVERYTHING, then the complexity could be hidden inside my 'type' grammar.
Jan 22 2003
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3E2ED62E.9010304 deming-os.org...I know that delegates are in. C-style function pointers still work as well (in DLI, at least). Is there any plan for delegate-style syntax of extern(C) function pointers?Daniel and I have talked about a unified syntax for delegates and function pointers, but so far it's just talk.The problem I'm facing is that I'm writing a parser for D.Why not just use the free one I supply? That way you're assured it will work just like the D compiler.
Jan 25 2003
Walter wrote:"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3E2ED62E.9010304 deming-os.org...The parser project started a long time ago. As it turned out, I've written from the ground up a whole new automatic parser generator - like Bison, but substantially more powerful. Developing a D parser has been a way to test the new utility. I have kind of fallen in love with the output of this new type of parser, so if I ever actually do any D development, I think my preference would be to use my parser rather than anybody else's. Anyhow, whether I ever use my parser or not, I think the issue still stands for *anybody* who will be writing a parser for D. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]I know that delegates are in. C-style function pointers still work as well (in DLI, at least). Is there any plan for delegate-style syntax of extern(C) function pointers?Daniel and I have talked about a unified syntax for delegates and function pointers, but so far it's just talk.The problem I'm facing is that I'm writing a parser for D.Why not just use the free one I supply? That way you're assured it will work just like the D compiler.
Jan 27 2003
Hi, Russ. How is your parser generator more powerful? If it's significantly better than Bison, are you putting it into the open source comunity? I'm just interested in case it's something I should be using. I currently do tons of Bison. Thanks, Bill Cox Russ Lewis wrote:Walter wrote:"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3E2ED62E.9010304 deming-os.org...The parser project started a long time ago. As it turned out, I've written from the ground up a whole new automatic parser generator - like Bison, but substantially more powerful. Developing a D parser has been a way to test the new utility. I have kind of fallen in love with the output of this new type of parser, so if I ever actually do any D development, I think my preference would be to use my parser rather than anybody else's. Anyhow, whether I ever use my parser or not, I think the issue still stands for *anybody* who will be writing a parser for D. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]I know that delegates are in. C-style function pointers still work as well (in DLI, at least). Is there any plan for delegate-style syntax of extern(C) function pointers?Daniel and I have talked about a unified syntax for delegates and function pointers, but so far it's just talk.The problem I'm facing is that I'm writing a parser for D.Why not just use the free one I supply? That way you're assured it will work just like the D compiler.
Jan 27 2003
Bill Cox wrote:Hi, Russ. How is your parser generator more powerful? If it's significantly better than Bison, are you putting it into the open source comunity? I'm just interested in case it's something I should be using. I currently do tons of Bison.Unfortunately, the company I work for is really strict about intellectual property issues. I hope to convince them to release it to the open source community, but for the moment I can't talk too much. In a nutshell (without revealing company secrets), it is 1) a GLR parser (though Bison just recently added this feature) 2) uses a syntax much like Bison, but FAR more expressive. Complex expressions that would have taken multiple rules in Bison can be expressed in a single line in my parser 3) parses the entire tree, returning a root object, rather than making you hand-code each and every rule 4) can handle (and return to you) multiple parsings, in case the language is ambiguous 5) outputted parser is in D, and thus the parser output is a tree of D objects I call it "cebu" - the C Enabled Bison Upgrade. It currently can generate parsers that parse D, and I believe that there is no reason it cannot parse C as well. As anybody who has used Bison knows, Bison cannot parse C without some massive hacks. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Jan 27 2003
Russ Lewis wrote:1) a GLR parser (though Bison just recently added this feature)Wonderful. This solves a myriad of problems.2) uses a syntax much like Bison, but FAR more expressive. Complex expressions that would have taken multiple rules in Bison can be expressed in a single line in my parserGood.3) parses the entire tree, returning a root object, rather than making you hand-code each and every ruleLike CocoM Early parser. (used in Dino)4) can handle (and return to you) multiple parsings, in case the language is ambiguousCocoM Early does this as well.5) outputted parser is in D, and thus the parser output is a tree of D objectsAnother similarity. Just that it's gonna be much faster than CocoM.I call it "cebu" - the C Enabled Bison Upgrade. It currently can generate parsers that parse D, and I believe that there is no reason it cannot parse C as well. As anybody who has used Bison knows, Bison cannot parse C without some massive hacks.Kewl :> Another difference of CocoM left, is that it can read a grammer at run time. It's a parser, not a parser generator. Another domain of use, at runtime, which also requieres that parser's internal structures must be built very quickly. -i.
Jan 27 2003
Hello. My opinion corresponds to: http://www.acm.org/crossroads/xrds7-5/bison.html So i hope yours *is* better than Bison. What algorithm(s) is it based on? I am going to write a easy-to-use parsing library for D, which would provide run-time extention. So it would not be a parser generator, rather something like Dino's runtime Earley parser. In fact, it might become an Earley parser. I might simply adapt it from Dino source, sice it's GPL and written in good C. The disadvantage is a lower speed - that's what compiler compilers adress. The distinct advantage of a run-time Earley parser would be, that no deep algorithm understanding is requiered, run-time extention is possible, as well as natural-language parsing. The run-time performance of a Dino's parser is about 30_000 C code lines per second on a 500Mhz P6, which i consider usually enough. And it requieres very little time to read in the grammar. It seems to me that parsing speed is not that important, since GCC uses a very fast parser, and is yet slow as hell. In fact the absolutely slowest compiler I've ever experienced. General design is of major importance. -i. Russ Lewis wrote:The parser project started a long time ago. As it turned out, I've written from the ground up a whole new automatic parser generator - like Bison, but substantially more powerful. Developing a D parser has been a way to test the new utility. I have kind of fallen in love with the output of this new type of parser, so if I ever actually do any D development, I think my preference would be to use my parser rather than anybody else's. Anyhow, whether I ever use my parser or not, I think the issue still stands for *anybody* who will be writing a parser for D.
Jan 27 2003
Ilya Minkov wrote: ...The run-time performance of a Dino's parser is about 30_000 C code lines per second on a 500Mhz P6, which i consider usually enough. And it requieres very little time to read in the grammar. It seems to me that parsing speed is not that important, since GCC uses a very fast parser, and is yet slow as hell. In fact the absolutely slowest compiler I've ever experienced. General design is of major importance.GCC isn't poorly designed as far as I can tell; it is slow as hell though. Assuming my cursory profiling of gcc is right, the single most expensive thing gcc does is garbage collection. The next most is parsing. Both of them make up the so much of compilation time that the backend seems irrelevent. I've been playing with 3.3 and 3.4 via CVS lately and follow some of the lists, and it looks like with a few gc tunables you can instantly squeeze out 25-40% more performance from it. Why they seem to have been neglected I have no idea. Maybe the gcc hackers are using super beefy hardware and haven't started seriously looking at the problem until lately when gcc 3.2.x was widely available to provide them with lots of complaints. General "design" as I read here and usually see tends to be restricted to considering long-term dominant characteristics. Have you ever seen how fast tinycc compiles C code? Lots of other compilers use the same kind of "algorithm" but so far as I can tell, the reason why its so fast is because it parses everything in one pass.
Jan 30 2003
Have I missed something here, but who cares how fast/slow the compiler is the important fact is does it generate fast code in an x86 the order is, (from some table I saw online last year) lcc (very poor) bc++, dmc (sorry walter, just going from figures I've seen), some gcc's are all about the same egcs and newer gcc a bit better VC++ generated code also twice the speed of lcc and 10 to 25% faster than bcc Intel's plugin for VS the top the next point of consern to me is; can I write code that's readable and know the compiler will optimise it fully, or do I have to write optimised C to get the performance. gcc suffers slightly from having such a range of backends, unlike tinycc, gcc generate an intermediate form of the code and passes that to the backend, and I would expect that its optimiser uses up a few cycles, I believe it performs at least two optimiser phases, first on the code (looking for loop invariants etc) then a simple peep hole optimiser on the generated code. and it makes tempary files for transfering info between front and backend afaik and it is this write read file access that will kill performance especially with files bigger than the file cache. if you are playing with gcc, you might want to try using named pipes for the connection between front end and backend on win32. just times some gcc compiler, I have a 6Mb 75 file GBA project compiling it 4 times (4 different configs) takes 1min 30sec at -O3 ; 1 min 25 at -O1 and 1 min 20 with no optimisation the longest file is a 4Mb lookuptable (int lut[16][0x8000]) which takes 12 seconds to compile only build into one version and that verison takes about 35 to 40 seconds to build this is on a Duron 800 512Mb RAM, UDMA66 disks Win2K (and all manner of junk running in the bg) I remember having a 2Mb Turbo Vision project that used to take over 30 minutes to compile on a P90 that, I call slow, but gcc, on current hardware (800 not exactly fast these days) I don't consider slow. I'll have to try on a realy slow machine (celeron 400) gc can be a killer to performance if you have HUGE amounts of object to walk, I made the mistake once of setting the java heap size bigger than my physical memory before running javadoc over some source, (this was at 6pm) I went out, stayed at a friends over night, got home and it was still parsing the files, every gc cycle was causing swapping, I think it took about 46 hour in the end, later I set the heap size just below the available mem, it took 4 hours instead :) like oo and templating, gc is just another double edged sword the programmer has to learn to work with. Mike. "Garen Parham" <garen_nospam_ wsu.edu> wrote in message news:b1b7na$65g$1 digitaldaemon.com...Ilya Minkov wrote: ...hackersThe run-time performance of a Dino's parser is about 30_000 C code lines per second on a 500Mhz P6, which i consider usually enough. And it requieres very little time to read in the grammar. It seems to me that parsing speed is not that important, since GCC uses a very fast parser, and is yet slow as hell. In fact the absolutely slowest compiler I've ever experienced. General design is of major importance.GCC isn't poorly designed as far as I can tell; it is slow as hell though. Assuming my cursory profiling of gcc is right, the single most expensive thing gcc does is garbage collection. The next most is parsing. Both of them make up the so much of compilation time that the backend seems irrelevent. I've been playing with 3.3 and 3.4 via CVS lately and follow some of the lists, and it looks like with a few gc tunables you can instantly squeeze out 25-40% more performance from it. Why they seem to have been neglected I have no idea. Maybe the gccare using super beefy hardware and haven't started seriously looking attheproblem until lately when gcc 3.2.x was widely available to provide them with lots of complaints. General "design" as I read here and usually see tends to be restricted to considering long-term dominant characteristics. Have you ever seen how fast tinycc compiles C code? Lots of other compilers use the same kind of "algorithm" but so far as I can tell, the reason why its so fast isbecauseit parses everything in one pass.
Jan 30 2003
Mike Wynn wrote:Have I missed something here, but who cares how fast/slow the compiler is the important fact is does it generate fast code in an x86 the order is, (from some table I saw online last year) lcc (very poor) bc++, dmc (sorry walter, just going from figures I've seen), some gcc's are all about the same egcs and newer gcc a bit better VC++ generated code also twice the speed of lcc and 10 to 25% faster than bcc Intel's plugin for VS the topCode generation is more important, but compile time performance is very important. When testing huge source trees it can mean a difference in days of time lost. All the waiting when developing adds up real fast too. I use icc 7.0 regularly and it has -O2 on by default and is 100-200% faster than gcc/g++ with no optimization, so I don't think its slow at all. It also uses the best C++ front end IMO and generates superior error messages.the next point of consern to me is; can I write code that's readable and know the compiler will optimise it fully, or do I have to write optimised C to get the performance. gcc suffers slightly from having such a range of backends, unlike tinycc, gcc generate an intermediate form of the code and passes that to the backend, and I would expect that its optimiser uses up a few cycles, I believe it performs at least two optimiser phases, first on the code (looking for loop invariants etc) then a simple peep hole optimiser on the generated code.There are lots of optimization passes that can be enabled, but the total time they take is miniscule IME.and it makes tempary files for transfering info between front and backend afaik and it is this write read file access that will kill performance especially with files bigger than the file cache. if you are playing with gcc, you might want to try using named pipes for the connection between front end and backend on win32.Using the -pipe flag won't generate temporaries.I remember having a 2Mb Turbo Vision project that used to take over 30 minutes to compile on a P90 that, I call slow, but gcc, on current hardware (800 not exactly fast these days) I don't consider slow. I'll have to try on a realy slow machine (celeron 400)When I first setup my environment to use tcc instead, I hit F8 to compile. It was so fast I just sat there wondering why nothing had happened. I didn't realize it had compiled already!like oo and templating, gc is just another double edged sword the programmer has to learn to work with.I don't follow that one.
Jan 30 2003
programmerlike oo and templating, gc is just another double edged sword thepeople were complaining that gcc is slow becasue it has gc (garbage collection) if used properly it can be faster (you avoid all those copy constructors, and code to keep track of live objects) you can also code complex meshes of objects without worring about who 'owns' what. on the down side, memory footprint can be bigger (you have to wait for the gc to run before you get your memory back) it all depends on the type of app you are writing. wjhat can I say it can be great if used in the right place, is can be a pain if used when it should not be. just like void*, OO, templates, innerclasses, nested classes, closures, inline asm etc etc etc all have their uses, and the more you used them the more you know when its right to do X and when X is going to bite back when your not looking.has to learn to work with.I don't follow that one.
Jan 30 2003
Mike Wynn wrote:I remember having a 2Mb Turbo Vision project that used to take over 30 minutes to compile on a P90 that, I call slow, but gcc, on current hardware (800 not exactly fast these days) I don't consider slow. I'll have to try on a realy slow machine (celeron 400)My main development computer is a notebook, Pentium MMX 233 MHz, 64 MB, Win98, which is lightweight enough that i carry it often with me to the university. Surprisingly enough, my math professor has a similar notebook, although he's not on a limited budget like i am.gc can be a killer to performance if you have HUGE amounts of object to walk, I made the mistake once of setting the java heap size bigger than my physical memory before running javadoc over some source, (this was at 6pm) I went out, stayed at a friends over night, got home and it was still parsing the files, every gc cycle was causing swapping, I think it took about 46 hour in the end, later I set the heap size just below the available mem, it took 4 hours instead :)Probably because it did a re-scan every time it hit the mem border. And/or went into swapping. Until it doesn't scan often, there should be no significant performance loss.like oo and templating, gc is just another double edged sword the programmer has to learn to work with.Sure. But like OO and Templating are very useful (even if not for all tasks), GC is as well. -i.
Jan 30 2003
Garen Parham wrote:GCC isn't poorly designed as far as I can tell; it is slow as hell though. Assuming my cursory profiling of gcc is right, the single most expensive thing gcc does is garbage collection. The next most is parsing. Both of them make up the so much of compilation time that the backend seems irrelevent. I've been playing with 3.3 and 3.4 via CVS lately and follow some of the lists, and it looks like with a few gc tunables you can instantly squeeze out 25-40% more performance from it.Does it do GC? Then why does it swap like hell on my 64mb notebook running lightweight win98? I've seen my allocated virtual memory constantly grow. It looks like it's plugged in where it doesn't do much? Perhaps non-GC-friendly data organisation? Besides, if it's boehm GC, it shouldn't be a significant performance loss. At least if it doesn't run the whole time. But yes, it would run the whole time if a system is forced to swap. :/Why they seem to have been neglected I have no idea. Maybe the gcc hackers are using super beefy hardware and haven't started seriously looking at the problem until lately when gcc 3.2.x was widely available to provide them with lots of complaints.:/General "design" as I read here and usually see tends to be restricted to considering long-term dominant characteristics. Have you ever seen how fast tinycc compiles C code? Lots of other compilers use the same kind of "algorithm" but so far as I can tell, the reason why its so fast is because it parses everything in one pass."It uses multiple simple short passes", it says in tinycc docs. And it also says that the only optimisations made are constant wrapping and replacements within single instructions (MUL to shift, ADD to INC, and so on), i.e. at generation. Unlike GCC or even LCC, it doesn't have means to edit generated code in any manner. It doesn't store an IR, i guess. And of course, it uses no intermediate assembly language file. I have a huge number of documents on my HD, describing different back-end generators for LCC. The major topic is rewriting the IR tree, selecting optimal choices guided by system-specific instruction-costs. I haven't had time to read them though and i won't for a short while. And yet, LCC is reasinably fast. LCC-Win32 gains additional performance because it doesn't save ASM files like original LCC and GCC do, but feeds it to internal assembler. But the assembly is still text, which is IMO simply stupid. It could be some uniform-sized binary data, which is easy to analyse and can be converted to real machine code with only a few shifts. LCC-Win32 adds a peephole optimizer to LCC, which tagges each text assembly instruction with a simple binary "description", and then does a simple pattern-search with replace between labels, using the tags as a primary guidance and also parsing single instructions when needed. Due to tags, the optimisation phase is very fast, and seems to add about 1/5 to compilation time. Simply imagine what if it had to parse ASM over and over. And GCC performance is very low as well with optimizations turned off. The LCC-Win32 author claims that a small number of simple optimisations leads to about 90% of GCC 2.95 code performance on P6 class machines, so it doesn't seem much like a speed-quality tradeoff, rather some deficiency in GCC. Avoiding the assembly phase is actually very simple, VCODE solves it in a following ANSI C -compliant manner: a number of preprocessor macros are written, one for each opcode, which generates the corresponding binary instruction using a couple of ANDs, ORs and shifts, and pushes it onto a kind of software-stack. Then, these only need to be placed instead of generating assembly text. Well, they obviously cannot be stored in an IR like text can, but some intermediate solution is imaginable. VCODE's IR storage is ICODE, just that these are made for runtime code generation, and represent a generalized RISC command set. But "back-ends" generating all kinds of machine code out of them exist. -i.
Jan 30 2003
Ilya Minkov wrote:Does it do GC? Then why does it swap like hell on my 64mb notebook running lightweight win98? I've seen my allocated virtual memory constantly grow. It looks like it's plugged in where it doesn't do much? Perhaps non-GC-friendly data organisation? Besides, if it's boehm GC, it shouldn't be a significant performance loss. At least if it doesn't run the whole time. But yes, it would run the whole time if a system is forced to swap. :/Yeah, GCC uses the boehm GC. C and C++ supposedly aren't very amenable to being GC'd but could hardly think it would amount to as much slowness as GCC shows."It uses multiple simple short passes", it says in tinycc docs. And it also says that the only optimisations made are constant wrapping and replacements within single instructions (MUL to shift, ADD to INC, and so on), i.e. at generation. Unlike GCC or even LCC, it doesn't have means to edit generated code in any manner. It doesn't store an IR, i guess. And of course, it uses no intermediate assembly language file.Yeah it doesn't do hardly anything at all for optimization. But with other compilers not getting even close without any optimization settings turned on it seems they can do way better.I have a huge number of documents on my HD, describing different back-end generators for LCC. The major topic is rewriting the IR tree, selecting optimal choices guided by system-specific instruction-costs. I haven't had time to read them though and i won't for a short while.... I've heard LCC was a good compiler to study but haven't read/used it. Have done some cursory browsing and it and the Zephyr/NCI projects seem pretty cool but look like they're dead.
Feb 01 2003
Garen Parham wrote:Yeah it doesn't do hardly anything at all for optimization. But with other compilers not getting even close without any optimization settings turned on it seems they can do way better.Eliminating intermediate structures speeds up compilation immensely, but also eliminates the possiblity of optimisation. Optimising compilers still need to build all their complicated intermediates, even if they're not optimising at the moment.I've heard LCC was a good compiler to study but haven't read/used it. Have done some cursory browsing and it and the Zephyr/NCI projects seem pretty cool but look like they're dead.And they're loose frameworks, not directly usable on x86. I bet you're not aware of this one: http://cocom.sourceforge.net/ (russian compiler/interpreter infrastructure) LCC works on x86, but it comes from Microsoft Research. The license is friendly to scientific/non-profit uses of it though. I bet .NET internals are similar to it. -i.
Feb 01 2003
Russell Lewis wrote:I know that delegates are in. C-style function pointers still work as well (in DLI, at least). Is there any plan for delegate-style syntax of extern(C) function pointers?I agree, the current function pointer syntax is weird; nontrivial usages of it are nearly incomprehensible. Howabout: type function ( declaration , ... ) IDENT; I don't like using "function", but it's the only name I can think of. Maybe we should get rid of function pointer types altogether. They're in the same fix as wchar; a language interface type that is badly supported and atrophying. You'll still be able to get the address of a function, but it'll be as a void pointer. The delegate of a function would be a minifunction that wraps the call properly: popl %eax // Put the return EIP in EAX movl %eax, (%esp) // Cover the null "this" pointer call function // Execute the real function jmp (%esp) // Jump to the caller Because the caller cleans up the stack in extern (D), we can't just substitute a "jmp function" in there and skip the last instruction; if we could, this could just be a couple bytes right before the real function and not have a jmp at all. Ironically, it would make calling class delegates faster than function delegates, but it wouldn't affect normal execution.
Jan 27 2003
Burton Radons wrote:The delegate of a function would be a minifunction that wraps the call properly: popl %eax // Put the return EIP in EAX movl %eax, (%esp) // Cover the null "this" pointer call function // Execute the real function jmp (%esp) // Jump to the callerWait, that's not right; the real function will still have four bytes too many on the stack, thanks to the call. Uh... I can't see how it can be done cheaply. We need the stack space, and we need to correct the stack before returning. This requires eight bytes, and we only have four to play in. If we put the this pointer at the end of the arguments this wouldn't be a problem. But that makes COM interfacing impossible. The only solution is to move the arguments down four bytes, stick the real return value after the arguments, and then correct later. This won't allow delegates for variadic functions, and of course it'll spike the speed hit considerably. Something like: movl (%esp), %eax // Put the return EIP in EAX movl %esp, %esi // Source part of the data move addl $4, %esi // Move from one cell up movl %esp, %edi // Destination part of the data move movl $argumentSize, %ecx // Number of bytes to move rep movsb movl %eax, argumentSize(%esp) // Stuff the return EIP call function // Execute the real function jmp argumentSize(%esp) // Jump to the caller Better than compiling two versions of every function.
Jan 27 2003
Burton Radons <loth users.sourceforge.net> wrote:If we put the this pointer at the end of the arguments this wouldn't be a problem.Oops, I missed this... :-(But that makes COM interfacing impossible.Though, the spec says that COM functions already need to use extern (Windows), so a change specifically to the D ABI shouldn't affect them. Of course, that raises the issue of what to do when extern (Windows (or any other ABI that may be supported)) functions are placed in a delegate, but it's better than having to apply the workaround to all functions. -Scott
Jan 27 2003
Burton Radons wrote:Maybe we should get rid of function pointer types altogether. They're in the same fix as wchar; a language interface type that is badly supported and atrophying. You'll still be able to get the address of a function, but it'll be as a void pointer.You could do that, except that we would need some syntax for interfacing with C code that requires function pointers. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Jan 27 2003
Russ Lewis wrote:Burton Radons wrote:Yeah, I think removing them wouldn't work; any method I can think of for calling them would be too asstastic, and unlike bitfields, there's going to be more function pointers in the future. Once delegates can be taken from a function, the pressure to have parallel APIs for both delegates and function pointers will be removed. You could even cast a function pointer to a delegate and vice versa with a little dynamic machine code generation. Hm.Maybe we should get rid of function pointer types altogether. They're in the same fix as wchar; a language interface type that is badly supported and atrophying. You'll still be able to get the address of a function, but it'll be as a void pointer.You could do that, except that we would need some syntax for interfacing with C code that requires function pointers.
Jan 27 2003
Burton Radons <loth users.sourceforge.net> wrote:The delegate of a function would be a minifunction that wraps the call properly: popl %eax // Put the return EIP in EAX movl %eax, (%esp) // Cover the null "this" pointer call function // Execute the real function jmp (%esp) // Jump to the caller Because the caller cleans up the stack in extern (D), we can't just substitute a "jmp function" in there and skip the last instruction; if we could, this could just be a couple bytes right before the real function and not have a jmp at all.What about modifying the ABI so that "this" is the last argument, rather than the first? Then, if it's not needed, it sits harmlessly on the stack like any other local variable of the caller. For ISAs with more registers, it may be better to dedicate an argument register to holding "this", so that the change doesn't incur a performance penalty by moving "this" from a register to the stack when the supply of argument registers is exhausted. Of course, this assumes that non-static methods are more frequent than static methods and plain functions, which would have one less argument register... -Scott
Jan 27 2003