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 multithreaded version of the 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’s 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 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
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.