From: SMTP%"RELAY-INFO-VAX@CRVAX.SRI.COM" 27-MAY-1993 13:59:04.05 To: EVERHART CC: Subj: Re: Q: Detecting number of arguments in VAX Fortran X-Newsgroups: comp.os.vms From: lionel@quark.enet.dec.com (Steve Lionel) Subject: Re: Q: Detecting number of arguments in VAX Fortran Message-Id: <1993May27.015018.22479@dbased.nuo.dec.com> Sender: news@dbased.nuo.dec.com (USENET News System) Organization: Digital Equipment Corporation Date: Thu, 27 May 1993 01:54:13 GMT Lines: 122 To: Info-VAX@kl.sri.com X-Gateway-Source-Info: USENET There's a lot of confusing, misleading, incomplete and sometimes just wrong information floating around this newsgroup on this subject. Some of it, I'm sorry to say, came from me, and I really should know better! So, here is all I know about the subject, including what happens on AXP. First, I will repeat what I said before. Both the DEC Fortran LRM and the Fortran-77 standard say that the number, type and order of the actual arguments (the ones in your CALL or function reference) must match those of the "dummy" (formal) arguments in the subroutine or function you are calling. This applies to calls to Fortran routines; when you call non-Fortran routines, different rules may apply. Now that I've gotten that out of the way, it is generally possible to write a Fortran routine for OpenVMS such that it can, with predictable results, be called with fewer actuals than dummys or with selected arguments "omitted" (by passing an immediate value of zero in the argument position). The exceptions to this are dummy arguments which are type CHARACTER or which are adjustable arrays (whose bounds are passed either in other arguments or in COMMON); for these two cases, the compiler will generate routine prologue code that fetches the argument descriptor (or address) and will typically give you an access violation if you omitted that argument in a call. Ok, you promise not to omit CHARACTER or adjustable array arguments. What's next is that there are two separate questions a routine may want to ask. I'll deal with these separately. The first is "how many arguments was I called with?" On VAX, this information is supplied in the first byte pointed to by register AP (R12) when a routine is called. The VAX compiler does not currently provide a means of getting at this value directly. What most people do is write a short MACRO function, such as was posted earlier, to get the "saved AP" value from the stack frame when the MACRO routine is called and extract the byte. There is a catch, though. The compiled Fortran code is free to use AP/R12 as a general register, so there's no guarantee that when you call your MACRO routine that the value of AP at that time will be what it was when the Fortran routine was called. However, the VAX compiler currently reuses AP only in a main program or a routine that has no declared dummy arguments. Furthermore, I think it's safe to say that the VAX compiler won't ever change its behavior in this regard. On AXP, it's more complicated. There is an argument count, but it isn't something you can reliably get by calling a MACRO routine. But relax, we didn't leave you hanging. The AXP compiler has an IARGCOUNT() intrinsic that will reliably return the argument count. I'll very likely add this to the VAX compiler in a future version. The second question is "was a particular argument passed by the caller?" An argument can be omitted in two ways. First, the argument list is short, and second, the argument list is not short but the argument address in the argument list is zero. If you've used one of the above methods to determine that the argument position is present, you can reliably test %LOC(arg) for zero to see if the argument was omitted. If you use this method, there's nothing else you need do; the compiler will give you a free VOLATILE declaration for the argument and won't do any optimizations that will touch the argument except when your code does so. It is important to use conditional code to prevent unwanted accesses to an argument which may be omitted and not rely on order of expression evaluation. For example, I saw a program which did something like this: IF ((%LOC(ARG) .NE. 0) .AND. (ARG .NE. 0)) ... This happened to work on a VAX system but not on an AXP system as the AXP compiler chose to evaluate the second subexpresion first, as it was free to do. It's safer to do it this way: IF (%LOC(ARG) .NE. 0) THEN IF (ARG .NE. 0) ... Now comes the confusing part, to which I have contributed mightily. I have been telling people that with V6 of the VAX compiler that you MUST use /ASSUME=DUMMY_ALIASES if your routine can be called with omitted arguments. This isn't strictly true. In particular, it's not true if you've used the %LOC method to determine if the argument was passed. Where it IS necessary is if the routine uses some OTHER method of determining whether or not the argument was passed, such as solely relying on the argument count or by looking at the value of some other argument. In this case, the V6 compiler may choose to perform a new optimization in which it makes a local copy of the argument in a register so that it can eliminate two memory references each time the argument is used. It does this by putting code in the routine prologue, before the first statement, to do the copy. If the argument was omitted, you might well get an ACCVIO as the code tries to fetch from address zero (or whatever happens to be at that position in the actual argument list.) You can disable this optimization by compiling with /ASSUME=DUMMY_ALIASES, which tells the compiler that it must assume that any dummy argument may be aliased (share storage with) some other argument or a COMMON variable. The V5 compiler made this assumption all the time, even though the Fortran-77 standard prohibits such aliasing. An example of this would be: CALL SUB (A,A) ... SUBROUTINE SUB (X,Y) This assumption prevents many useful optimizations, and most Fortran programs don't have such aliasing, so the V6 compiler was changed to assume NODUMMY_ALIASES and the qualifier was created so that you could tell the compiler that you might have aliasing. As I noted before, you can put this qualifier in an OPTIONS statement. The AXP compiler does the same optimization, but in a different way so that a problem is less likely to occur. Still, it's safest to use the qualifier if you're NOT using %LOC or VOLATILE on the argument name. (Oh yeah - on AXP, some arguments are passed in registers, but if you use %LOC, the compiler "homes" the argument list to memory so that it works as it does on a VAX.) So... If your Fortran routines use %LOC to test whether an argument is present, V6 shouldn't break your application. If you use some other method, you'll need to use /ASSUME=DUMMY_ALIASES. I'll try to get this all in the documentation and/or release notes in future versions. Steve Lionel lionel@quark.enet.dec.com SDT Languages Group Digital Equipment Corporation 110 Spit Brook Road Nashua, NH 03062