!topic LSN on Access to Machine Operations !key LSN-1072 on Access to Machine Operations !reference RM9X-G.1;4.0 !from Offer Pazy $Date: 94/01/28 17:02:29 $ $Revision: 1.9 $ !discussion At the last XRG meeting (12/93) a resolution was approved to relax the requirements in G.1(3) and G.1(5) and make them implementation advice (IA). The background and reasons for this decision are summarized below. The purpose of this LSN is to capture the various arguments on this issue; to rationalize why the resulting situation is not satisfactory, and to propose other solution(s) that will hopefully achieve wide consensus. BACKGROUND: ----------- The need for the System Programming (SP) Annex to support some kind of low level access to the underlying hardware has received wide-spread consensus. In fact, this was one of the primary goals of the annex to start with. The objectives of the SP annex are listed in the introduction to chapter III-2 of the rationale. Two methods were considered for achieving this goal: the Interface pragma to an assembler, and the Machine_Code package (MCI). The third related capability, the intrinsics, is somewhat similar, but its purpose is different: using P. Hilfinger terminology, intrinsics are geared more towards "open routines" where the intrinsics code is combined and possibly optimized together with the Ada code. MCI, on the other hand is needed for explicit and direct programming at a low level. The main motivation for this section in 9X is the previous, less-than-satisfactory experience with Ada-83 compilers. MCI existed before, but its support was non uniform and lacking in many respects. [A side note: Several reviewers have expressed the opinion that standards should not be used to obtain "non-portable" tools from vendors if market forces could not make the same tools available otherwise. I disagree, the purpose of standards (among other things) is to focus implementor's attention on areas that the users perceive as important. With 9X, there is a strong competition on vendor's resources, and optional features are likely to be delayed in their implementation. Lack of focused attention was one of the reasons (IMHO) that support for MCI was less then ideal in Ada 83; it took vendors several years to understand the priorities of the market. The SP annex is directed to a slice of the market where such a feature is believed to be very important. End of side note] THE PROBLEM: The problem is that this area is quite difficult to standardize on. As many have correctly claimed, it is at least useless and probably harmful, to include non-testable normative text in the standard. Since the term "machine operations" is so vague and differs in meaning from one machine to another, it is quite difficult to require that "all" will be supported. Specifically: - It is not clear what constitutes a machine instruction: any possible OP-code ? Any assembler mnemonic, any legal bit pattern in the OP-code field ? - What is a machine operation ? Is it just the "useful instructions", as was originally our intention when writing the annex ? Is it *any* activity that may be performed on the machine (load a tape, shutdown, etc.) ? Clearly we need to have a fairly specific definition here. - Many HW systems have a host of unofficial and/or undocumented features, some of them are invoked with OP-codes. Will these be required ? Clearly, on many occasions this will be impossible for the vendor to provide. However, one should not confuse the above issue with the problem of issuing dangerous/supervisor/privileged instructions. Just as assembler code can issue such instructions, so should an Ada code be able to do the same. After all we do want to be able to write kernels, OS's, etc. in Ada. Usually the HW and/or the operating system contain enough protection mechanisms to ensure that such instructions are not issued in the wrong context. These mechanisms will similarly apply to Ada code. Neither the language, nor the compiler should be in the business of understanding what a dangerous instruction is or enforcing the correct usage. These questions emphasize that if we want to make this requirement a real one, we cannot just say "all" without creating an impossible validation situation. On the other hand, just saying "please provide some access to what you, the vendor, think is important", is not good enough (in my view) for portability and minimal uniformity. [A side note on portability: Readers may be surprised to find the "portability" goal in such a HW-specific context. I believe that this goal has two meanings here: - a partial uniformity between two compilers targeted to the same HW, and - "portability of functionality": i.e. the ability of a system designer to be confident, no matter which compiler he chooses for his project (and before he does so), that he will be able to have access to the underlying hardware as long as the compiler he chooses has the SP label. How this will be done and the compiler quality will remain open questions of course, but the knowledge that *some* way to do this exists, is quite important. (Sort of like choosing Ada because it has tasking.) End of side note] SO WHAT ARE OUR OPTIONS ? There are several directions we could go in order to address this problem: - Strengthening the Implementation Advice sections: Apparently, some reviewers had a view of this sub-heading which is quite different from what the MRT has intended (the MRT view is summarized in AARM-1.1.3(20-20.e). We really meant it to be a friendly advice to the implementors, sort of "take it or leave it". The other view was that such advice has much more power behind it, and the implementor should follow it unless he has a good reason not to. If we redefine the meaning of the IA sections along these new lines, then we may have a solution. The fear that non-normative text will simply be ignored by overloaded implementors is reduced, and we get a good combination of stating the real intent of the standard without being bogged down with requirements that are impossible to state normatively. It is important to note here that this was, after all, one of the purposes of the SP annex, to focus implementors' attention on areas that are believed to be important to users. We want to do the maximum that will encourage implementors to provide the needed functionality, but that on the other hand will not create an unnecessary burden in worrying about meaningless requirements. Usually, to balance this tension, we either state a requirement and then add a specific permission; or we provide an IA. The former is perceived to have a stronger effect, and is the subject of the second alternative further below. If we stick with an IA, we should add a requirement (DocReq) to document those machine operations that are not supported by an implementation. The idea behind this requirement is first to make the implementation choice more visible to users. Second, it is meant to provide a stronger incentive to implementors to really provide what makes sense on a given target. This is achieved by requiring a positive action on their part, as opposed to "quietly" ignoring IAs. It is not suggested, however, that these documentation requirements will be somehow subject to quality standards, validation or anything similar. Here, we can rely on vendors not to put information that might later embarrass them. So, it will be up to the vendor (!) to decide how much documentation to provide for unsupported operations. After all, if we could entirely rely on implementors and market forces, much of the reason behind the SP annex would go away. We do want to help implementors in directing their efforts towards providing useful functionality. However, in order to take this approach, some other issues have to be addressed: - This change of the meaning of IAs, is a global one and will require achieving an appropriate level of support before it can be adopted. - Also, IAs are used all over the RM; they were written with the original MRT intent in mind, and some of them may not fit the new model. We don't want to blindly strengthen requirements that were really meant just as an advice. We will need to review all such sub-headings and potentially edit some, remove others, or relocate to the AARM. We don't anticipate a major problem here except the actual work. Finally, since interfacing to an assembler has also been moved to an "advice" status (and frankly, the combination of these two changes caused much of the debate), the change suggested above might help here as well. I believe that we do have a consensus on the requirement that on a given target, an assembler should be supported, if it is readily available. The problem is that there are some marginal situations which caused drafting a normative requirement a bit difficult. The solution of "strong IA" seems to fit nicely here as well. But, if there is no assembler on a target (or it is not supported), a powerful MCI capability *is* critical for the kinds of software this annex is intended to support. Note: Even if we choose this approach, it is beneficial to define, as precisely as we can, what we mean by the term "operation code". A similar text to the one below will still exist, but in the IA sub-heading. - Rewording the requirement: An alternate option is to stick with the current approach to the requirement (for the majority of the cases), and a meaningful permission that will provide vendors with an escape clause, if the requirement for "all machine operations" really does not make sense on a given target. We have taken this approach elsewhere too. We use it mainly to preempt likely AI-325 arguments in the future when we anticipate them. Here is a suggestion for a revised wording of the corresponding paragraphs. It is hoped that the problems discussed above go away with the new formulation of the rule. The general strategy is to establish a clear requirement, based on the concept of "instruction set architecture," and then to add permissions as necessary to to make the requirement realistic. @Defn{operation code} For the purpose of these paragraphs, @i{operation code} is defined as a distinct bit pattern in the hardware instruction word(s) that specifies the function performed by the instruction, as contrasted with @i{operand fields} which are the portion of the instruction that specify particular parameter objects of the instruction. Implementation Requirements The implementation shall support machine code insertions or intrinsic subprograms, and all of the distinct operation codes of the target instruction set architecture shall be accessible through one or the other. Implementation Permissions Implementations need not support operation codes that are reserved to the hardware implementation, or that are not widely and publicly available and documented. @Ramification{This permission does not remove the requirement to support operation-codes that are privileged or may be issued only in a supervisor-mode. These have to be made accessible unless they fall under one of the other categories.} For machine code insertions, not all addressing modes need be supported for every operation code, so long as sufficient addressing modes are available on memory-oriented operations to refer to the parameters of a machine code subprogram, and to Ada entities declared global to the machine code subprogram. Where the implementation makes use of a standard object code format for the target architecture, the implementation is not required to support forms of instructions that are not supported by the object code format. SUMMARY: I believe that any of the alternatives outlined above can satisfy the requirement in a language-consistent manner. The first alternative has the benefit that it does not depend on a precise and legalistic definition of what is an operation code; however, it relies on changing the meaning of a well-established concept of Ada 9X (IA). The second alternative attempts to fix the problem at the source, by suggesting a better set of definitions. The MRT does not have a strong preference on which approach to adopt.