From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,b1f4420d01b2c4eb X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!newsfeed2.dallas1.level3.net!news.level3.com!newsfeed-00.mathworks.com!nntp.TheWorld.com!not-for-mail From: Robert A Duff Newsgroups: comp.lang.ada Subject: Re: LLVM--Low Level Virtual Machine--and Ada Date: Fri, 20 Jul 2007 10:06:25 -0400 Organization: The World Public Access UNIX, Brookline, MA Message-ID: References: <1184730995.862147.208590@g12g2000prg.googlegroups.com> NNTP-Posting-Host: shell01.theworld.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: pcls4.std.com 1184940385 9322 192.74.137.71 (20 Jul 2007 14:06:25 GMT) X-Complaints-To: abuse@TheWorld.com NNTP-Posting-Date: Fri, 20 Jul 2007 14:06:25 +0000 (UTC) User-Agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.3 (irix) Cancel-Lock: sha1:iIdH9aJT7V53QsIYJUNmtQ+RHGo= Xref: g2news1.google.com comp.lang.ada:16526 Date: 2007-07-20T10:06:25-04:00 List-Id: Duncan Sands writes: >> > PS: the only thing that needed new LLVM functionality, >> > i.e. functionality that didn't exist and wasn't being >> > worked on, was pointers to nested functions. >> >> How did you implement those? >> >> GNAT uses trampolines, which are less than ideal >> for several reasons. > > Hi Bob, I used trampolines. I really couldn't do it any other > way without a bunch of modifications to the GNAT front-end. > Also, this seems to be the only solution if you want to be able > to pass such pointers to foreign language routines, which seems > nice to have if not essential. The major downside I see is that > they seem to be extremely expensive, presumably because you take > an icache hit every time you jump to the stack. I plan to implement > a bunch of small optimizations which may help, such as converting > direct calls to trampolines into direct calls to the nested functions > (inlining hopefully will create such direct calls). Any suggestions > for a better approach than trampolines? I'm also curious to hear > what the other less than ideal properties of trampolines are! The main problem with trampolines is what you said -- they're slow. Another problem is that some modern machines use DEP (which I think stands for "data execution prevention" or something like that). DEP means the operating system prevents writeable data from being executed as code. The purpose is to prevent certain kinds of security holes that are common in languages that don't do array-bounds checking. But DEP prevents trampolines from working, so users have to turn it off in order to run some Ada programs (such as the compiler). It's a pain because users get some mysterious error message when trampolines are used. Another problem (I've heard) is that there's at least one machine supported by gcc where trampolines don't work. I don't remember which machine, and I don't even know for sure that this is true. The alternative to trampolines is to represent access-to-nested-subprogram as a pair, sometimes called a "fat pointer": (address-of-code, static link). AdaCore is thinking about doing this at some point. You are correct that this won't work when interfacing to C. The answer is: if the Convention of the access type is C, and the procedure is nested, use a trampoline. Trampolines are probably also required for 'Unrestricted_Access, because it allows you to bypass the normal accessibility rules. Access-to-nested subp is much more important in Ada 2005 than in Ada 95, because we now have downward closures. (See the Iterate procedures in the Containers packages for examples.) When using downward closures, you almost always want nested subprograms. (Downward closures are one of my favorite features, by the way.) Another issue is nested type extensions -- dispatch tables contain pointers to subprograms. E.g. type T1 is library level, and "T2 is new T1" is nested. The primitives of T2 need a static link. You don't want to store static links for T1 -- that would be a distributed overhead. T2's primitives can be trampolines, but that's inefficient. There's a trick mentioned in the AI that introduced this feature: store the static link as an implicit component of T2. T2's primitives can be a wrapper that loads the static link and then calls the user-defined code. This eliminates any overhead on T1, and is still more efficient than trampolines for T2. See the AI for details. One use for nested type extensions is when you want a Finalize procedure of a controlled type to be nested. - Bob