As described above, ‘pragma foreign_proc’ declarations may include a list of attributes describing properties of the given foreign function or code. All Mercury implementations must support the attributes listed below. They may also support additional attributes.
The attributes which must be supported by all implementations are as follows:
This attribute declares whether or not execution inside this foreign language code may call back into Mercury or not. The default, in case neither is specified, is ‘may_call_mercury’. Specifying ‘will_not_call_mercury’ may allow the compiler to generate more efficient code. If you specify ‘will_not_call_mercury’, but the foreign language code does invoke Mercury code, then the behaviour is undefined.
This attribute promises that the purity of the given predicate or function definition is pure or semipure. It is equivalent to a corresponding ‘pragma promise_pure’ or ‘pragma promise_semipure’ declaration (see Impurity). If omitted, the clause specified by the ‘foreign_proc’ is assumed to be impure.
This attribute declares whether or not it is safe for multiple threads to execute this foreign language code concurrently. The default, in case none is specified, is ‘not_thread_safe’. If the foreign language code is declared ‘thread_safe’, then the Mercury implementation is permitted to execute the code concurrently from multiple threads without taking any special precautions. If the foreign language code is declared ‘not_thread_safe’, then the Mercury implementation must not invoke the code concurrently from multiple threads. If the Mercury implementation does use multithreading, then it must take appropriate steps to prevent this. (The experimental multithreaded version of the current University of Melbourne Mercury implementation protects ‘not_thread_safe’ code using a mutex: C code that is not thread-safe has code inserted around it to obtain and release a mutex. All non-thread-safe foreign language code shares a single mutex.) If the foreign language code is declared ‘maybe_thread_safe’ then whether the code is considered ‘thread_safe’ or ‘not_thread_safe’ depends upon a compiler flag. This attribute is useful when the thread safety of the foreign code itself is conditional. The Melbourne Mercury compiler uses the ‘--maybe-thread-safe’ option to set the value of the ‘maybe_thread_safe’ attribute.
Additional attributes which are supported by the Melbourne Mercury compiler are as follows:
This attribute should be attached to foreign procedures that do I/O. It tells the debugger to make calls to the foreign procedure idempotent. This allows the debugger to safely retry across such calls and also allows safe declarative debugging of code containing such calls. For more information see the I/O tabling section of the Mercury user guide. If the foreign procedure contains gotos or static variables then the ‘pragma no_inline’ directive should also be given. Note that currently I/O tabling will only be done for foreign procedures that take a pair of I/O state arguments. Impure foreign procedures that perform I/O will not be made idempotent, even if the tabled_for_io attribute is present. Note also that the tabled_for_io attribute will likely be replaced in a future release with a more general solution.
This attribute specifies the termination properties of the given predicate or function definition. It is equivalent to the corresponding ‘pragma terminates’ or ‘pragma does_not_terminate’ declaration. If omitted, the termination property of the procedure is determined by the value of the ‘may_call_mercury’/‘will_not_call_mercury’ attribute. See Termination analysis for more details.
This attribute declares the maximum stack usage of a particular piece of code. The unit that ‘Size’ is measured in depends upon foreign language being used. Currently this attribute is only used (and is in fact required) by the ‘IL’ foreign language interface, and is measured in units of stack items.
This attribute promises that the given predicate or function will not make calls back to Mercury that may result in an exception being thrown. It is an error to apply this attribute to procedures that have determinism erroneous. This attribute is ignored for code that is declared as not making calls back to Mercury via the ‘will_not_call_mercury’ attribute. Note: predicates or functions that have polymorphic arguments but do not explicitly throw an exception, via a call to exception.throw/1 or require.error/1, may still throw exceptions because they may be called with arguments whose types have user-defined equality or comparison predicates. If these user-defined equality or comparison predicates throw exceptions then unifications or comparisons involving these types may also throw exceptions. As such, we recommend that only implementors of the Mercury system use this annotation for polymorphic predicates and functions.
This attribute declares whether or not a foreign procedure modifies the trail (see Trailing). Specifying that a foreign procedure will not modify the trail may allow the compiler to generate more efficient code for that procedure. In compilation grades that do not support trailing this attribute is ignored. The default, in case none is specified, is ‘may_modify_trail’.
This attribute declares whether or not a foreign procedure makes calls back to Mercury procedures that are evaluated using minimal model tabling (see Tabled evaluation). Specifying that a foreign procedure will not call procedures evaluated using minimal model tabling may allow the compiler to generate more efficient code. In compilation grades that do not support minimal model tabling this attribute is ignored. These attributes may not be used with procedures that do not make calls back to Mercury, i.e. that have the ‘will_not_call_mercury’ attribute. The default for foreign procedures that ‘may_call_mercury’, in case none is specified, is ‘may_call_mm_tabled’.
This attribute declares whether or not a foreign procedure uses and/or modifies any part of the Mercury virtual machine (registers, stack slots) through means other than its arguments. The ‘affects_liveness’ attribute says that it does; The ‘does_not_affect_liveness’ attribute says that it does not. In the absence of either attribute, the compiler assumes ‘affects_liveness’, unless the code of the foreign_proc in question is empty.
This attribute tells the compiler whether it is allowed to duplicate the foreign code fragment through optimizations such as inlining. The ‘may_duplicate’ attribute says that it may; The ‘may_not_duplicate’ attribute says that it may not. In the absence of either attribute, the compiler is allowed make its own judgement in the matter, based on factors such as the size of the code fragment.