Benjamin Kowarsch <trijezdci@gmail.com> writes:
> On Mon, 18 Dec 2023 at 07:59, Michael Riedl wrote:
>
> I have the same issue - all my binding (in may case mostly to Fortran
>
> <snip>
>
> ... what are the benefits of adding an "EXPORT QUALIFIED" statements
>
> EXPORT is not a statement but a directive.
>
> to an interface to another language which never prefixed ("C") or,
>
> in case of Fortran Modules, in a different way ?
>
> I agree with the notion that it makes no sense for a Modula-2 compiler to
> generate prefixed names from an interface to a library in a language that
> doesn't use name mangling or that uses a different name mangling convention.
>
> Generating names that comply with the calling convention of the interfaced to
> language should be the purpose of the FOR "language" directive in the module
> header. And calling convention does not only consist of parameter passing, it
> also means matching any name mangling convention of the interfaced to language.
>
> In M2R10 we specified the FFI directive in the module header this way.
>
> INTERFACE MODULE Foo <*FFI="C"*>;
> (* foreign function interface to C, including C naming *)
>
> Suppose, the foreign library uses names that we cannot express in Modula-2
> due to characters being allowed in identifiers that are not legal in Modula-2,
> or we simply want to make the Modula-2 side source code comply with
> Modula-2 naming conventions. In this case, it makes far more sense to
> provide a directive to specify the illegal or unliked foreign name within
> a declaration that introduces that name:
>
> PROCEDURE FooBarBaz <*FFINAME="FOO$BAR_BAZ"*> ( bam : Bam; boo : Boo );
>
> But even in that case, the compiler should generate a name for FOO$BAR_BAZ that
> complies with any name mangling convention of the language specified in the FFI
> directive in the module header. No other directive to interfere with that mechanism.
>
> I cannot think of any use case where one might want or need to generate a mangled
> name for a foreign library object of a language that doesn't use name mangling, as
> is the ase with C. However, even if there was such a use case, it should be dealt
> with in a different manner and it should certainly not be default behaviour. It should
> be exceptional behaviour triggered by a directive specifically provided for that purpose.
>
> PROCEDURE Foobar <*NAMEMANGLING=ON*> ... ;
>
> or something like that.
>
> In summary, I would consider the observed behaviour a bug, not a feature.
>
> regards
> benjamin
>
> Am 12.12.23 um 22:22 schrieb Philip Munts:
> > It appears to me that in GCC 12.3.0, externals declared in a C binding
> > module (DEFINITION MODULE FOR "C") are not mangled, but in GCC 13.2.0
> > they *are* mangled, prefixing the module name.
> >
> > Given:
> >
> > DEFINITION MODULE FOR "C" Foo;
> >
> > PROCEDURE Bar;
> >
> > END FOO;
> >
> > Linking a program that calls Foo.Bar in 12.3.0 requires the external C
> > function to be named Bar while 13.2.0 requires it to be Foo_Bar.
> >
> > This is a severe pain in the neck, as I have a substantial number of
> > such C binding modules that all have to be rewritten for GCC 13,
> > adding EXPORT QUALIFIED for every C external. I opine that external C
> > names should never be mangled...
> >
> > Phil
Hi,
I guess one of the problems with non-standard extensions using keywords
is that there is some indirection leading to differing default
expectations of what is implied by the use of the FOR "C" with
UNQUALIFIED/QUALIFIED. In particular the intersection between two
extensions :-)
The problem is this:
What is the purpose of the FOR "C" syntax if not specifying that the module is a foreign function interface for a C library? And if that is its purpose, then the compiler should follow any and all C calling and naming conventions.
If it does not follow C calling conventions, then the module cannot be used as a foreign function interface to C and then does not fulfill the intended purpose. Likewise if it does not follow C naming conventions (flat namespace) then it also does not fulfill the intended purpose.
In fact, if the syntax FOR "C" does not cause the compiler to use both C calling and naming conventions, then it has no purpose at all other than perhaps being a comment for a human reader.
Therefore I wonder whether it might be pragmatic to migrate to the <*
attribute *> mechanism to select features rather than rely on the FOR
"C" and UNQUALIFIED keywords to turn on/off features. The UNQUALIFIED
extension (a keyword not in iso or pim) pre-dates the iso standard.
Given iso allows for <* *> I propose the following:
(i) introduce attributes to explicitly control
the behaviour of the definition module. For example
gcc/m2/gm2-libs/libc.def would start:
DEFINITION MODULE libc ;
<* name_mangling (FALSE); calling_convention ("C");
module_registration (FALSE) *>
In my view it is preferable to use a pragma instead of language syntax to specify whether a definition module is a foreign function interface to a foreign library. However, like any other things, specifying a foreign function interface should not be made any more complicated than necessary. It should be as simple as specifying the target language.
DEFINITION MODULE FooLib <*FFI="C"*>;
First, we should consider the question when to use language syntax and when to use pragmas. In our revision leading to M2R10 we pondered this question and came to the conclusion that syntax should be used whenever the functional semantics of the source code are specified. By contrast, pragmas should be used whenever the compiler is given directions to guide the translation process but not changing the functional semantics.
For example, when building a single pass compiler that may require a forward declaration, this does not actually change the functional semantic of the source code, it is merely a compilation aid. Therefore, in M2R10, there is no forward declaration syntax, but an optional forward pragma that can easily be ignored by compilers that don't need such a compilation aid.
For interface modules that specify a foreign function interface to a foreign library, the functional semantics should be the same as if the module was an interface to a library written in Modula-2. Using foreign function interfacing conventions is merely a hint to the compiler how to translate the source code, not an alteration of functional semantics. Therefore, in M2R10, there is no language syntax to specify a foreign function interface, but a pragma.
Thus
INTERFACE MODULE FooLib <*FFI="C"*>;
If somebody decides at some point in the future to reimplement the foreign library in Modula-2, they should only need to remove the pragma from the module header and all else stays the same. Likewise, if somebody decided to reimplement the foreign C library in a different language, it should be as simple as changing the name of the target language (provided that the compiler supports that target language).
There really is no reason to separate different aspects of a foreign function interface and provide one pragma for the calling convention and another for name mangling. A C library will never use name mangling. A library for another language that does use name mangling will always mangle names in a specific way. Therefore, whether or not names are mangled, and if so, how they are mangled is a necessary aspect of interfacing to that language and thus it should already be covered by specifying the target language. There is no sense in separating this out.
And if you intend to write a Modula-2 library that is intended for use by code written in C just as if it was also written in C, then this is a different use case. And this use case does not really need any syntax nor any pragma. Instead, it should be supported by compiler switch specifying the compilation target. Compiling a library that targets C is in principle no different from one that targets a specific hardware platform.
One does NOT do
IMPLEMENTATION MODULE Foo FOR "ARM";
so why should there be any syntax for targeting C or any other language environment?!
Thus, I say, please consider adopting an FFI pragma
DEFINITION MODULE FooLib <*FFI="C"*>;
and then let the compiler follow any and all conventions necessary to interface to the specified foreign language.
Remember, things should be made as simple as possible, not any simpler, but also not any more complicated.
regards
benjamin