July 17, 2019
On Wednesday, 17 July 2019 at 04:43:52 UTC, Manu wrote:
> On Tue, Jul 16, 2019 at 9:40 PM Nicholas Wilson via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>
>> On Wednesday, 17 July 2019 at 04:05:57 UTC, Manu wrote:
>> > One hopefully trivial request, I wouldn't want the compiler to emit a single header; I would want it to emit one .h per .d file into the output directory.
>>
>> Forward declarations make that a PITA.
>
> Hmmm...

You could possibly achieve something sensible with package at a time compilation though.
July 17, 2019
I considered suggesting something like this.
But I'm not sure either way, it really depends on how portable it would be.

Also there are COM classes to think about too.
July 17, 2019
On Tue, 16 Jul 2019 at 15:20, Eduard Staniloiu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> Project goal
> ------------
>
> The deliverable of the project is a tool that automatically
> generates C and C++
> header files from D module files. This can be achieved either by
> a library solution using
> DMD as a Library, or by adding this feature in the DMD frontend
> through a compiler
> switch.
>
> The advantage of using DMD as a Library is that this wouldn’t
> increase the
> complexity of compiler frontend codebase. The disadvantage will
> be that the user will be
> required to install a third-party tool. Contrasting to this, the
> addition of the feature to the
> frontend would result in a smoother integration with all the
> backends that use the DMD
> frontend.
>
> We have decided to go with the compiler switch approach.
>
> One major milestone (and success marker) for the project is to
> automatically generate the
> DMD frontend headers required by GDC/LDC.
>

As there will be for a long time the need to bootstrap, I think the desired end result would be to have the generated header checked in to dmd, and for this header to be rebuilt during the 'make' build process.

The CI infrastructure we have can then assert that this header doesn't change during the build, so PRs should never forget to check-in the new header.

>
> So now, the current state of affairs is that the code in the PR [0] can link with and pass the `cxx-unittests`.
>

So it's probably worth giving the generated header a test against gdc then.

https://github.com/gcc-mirror/gcc/tree/ibuclaw/gdc


> How to use it
> -------------
>
> The current PR [0] code is generating a `C++` header file out of a list of `.d` modules passed at compile time.
>
> The simplest form of the CLI switch is `dmd -HC a.d b.d`
>
> This will visit the ASTs of modules `a` and `b` and output a single header file at `stdout`.
>
> By using the `-HCf=<file-name>` switch, the above result will be written in specified file name. Using `-HCd=<path>` will write the `file-name` in the specified `path`.
>
> So, by running,
> `dmd -HCf=ab.h -HCd=mypath/ a.d b.d` will write the generated
> header in `mypath/ab.h`, relative to the current directory.
>
> If you have some spare time and curiosity I would appreciate your `test drive` and bug reports :)
>

So this would be part of the compiler rather than a standalone application?  What's the rationale there?

-- 
Iain

July 17, 2019
On Wednesday, 17 July 2019 at 11:52:17 UTC, Nicholas Wilson wrote:
> On Wednesday, 17 July 2019 at 11:05:21 UTC, Eduard Staniloiu wrote:
>> On Tuesday, 16 July 2019 at 13:46:56 UTC, rikki cattermole wrote:
>>> So currently there is no way to restrict it to just extern(C)?
>>> I ask this because -HC makes me think C not C++ headers.
>>
>> Currently the outputted headers are C++ headers, but we were thinking of wrapping `extern (C++)` definitions inside an `#ifdef __cplusplus` block, and prefixing any `extern (C)` definitions with the following `EXTERNC` macro
>>
>> ```
>> #ifdef __cplusplus
>> #define EXTERNC extern(C)
>> #else
>> #define EXTERNC
>> #endif
>> ```
>>
>> This way, the generated header could be used in both C and C++.
>>
>> What do you think?
>
> It should be pretty trivial to just check the linkage of the symbols and only output extern(C) symbols.

This would require two compiler switches, one for C (-HC ?) and one for C++ (-HCPP ?).
Was trying to keep it as one compiler switch.

>
> Also you've clearly been doing too much D programming! (which is probably a good thing) That would be:
> #define EXTERNC extern "C" {
>
> and you need to macro the closing brace as well.

Good catch! Thank you
July 17, 2019
On Wednesday, 17 July 2019 at 12:40:38 UTC, Iain Buclaw wrote:
> On Tue, 16 Jul 2019 at 15:20, Eduard Staniloiu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> [...]
>
> So it's probably worth giving the generated header a test against gdc then.
>
> https://github.com/gcc-mirror/gcc/tree/ibuclaw/gdc
>

I'll give this a shot. Could you please give me a helping hand on how to get gdc to compile with the generated `frontend.h`?

>
>> [...]
>
> So this would be part of the compiler rather than a standalone application?  What's the rationale there?

Keeping it as part of the compiler doesn't require to redo all steps that `mars.d` does and it is also consistent with the current `.di` and `.json` generators.

July 17, 2019
On Wed, 17 Jul 2019 at 15:25, Eduard Staniloiu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Wednesday, 17 July 2019 at 12:40:38 UTC, Iain Buclaw wrote:
> > On Tue, 16 Jul 2019 at 15:20, Eduard Staniloiu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> >> [...]
> >
> > So it's probably worth giving the generated header a test against gdc then.
> >
> > https://github.com/gcc-mirror/gcc/tree/ibuclaw/gdc
> >
>
> I'll give this a shot. Could you please give me a helping hand on how to get gdc to compile with the generated `frontend.h`?
>

Should be straightforward, all front-end includes have the explicit path, e.g:

#include "dmd/aggregate.h"

Just replace them with:

#include "dmd/frontend.h"

And see if it fails to compile or bootstrap. :-)

> >
> >> [...]
> >
> > So this would be part of the compiler rather than a standalone application?  What's the rationale there?
>
> Keeping it as part of the compiler doesn't require to redo all steps that `mars.d` does and it is also consistent with the current `.di` and `.json` generators.
>

But apart from the construction (and possible destruction) of all frontend types, there shouldn't be anything duplicated.

Did you consider cross compiler generation?

-- 
Iain
July 17, 2019
I want to give a heads-up to everyone for the following issue (this had me scratching my head for a couple of days unit I caught it):

The current code doesn't take into account `enum BaseType`s, ex:
```
enum TOK : ubyte { /* ... */ }

class Expression
{
  TOK op;
  /* ... */
}
```

The `enum TOK` above gets generated as
```
enum TOK { /* ... */ }
```

According to the C standard, the compilers are free to pick the type that can fit the enum and most of them will pick `int` as a base type; thus `sizeof(TOK) -> 4UL`.
As you can see, this is a problem as the D object files will consider `TOK` to be one byte and the C object files will consider it to be four bytes.

The manual header implementation did this clever trick to solve the problem
```
#typedef unsigned char TOK;
enum
{
  TOKmem1,
  /* ... */
};

class Expression
{
  TOK op;
  /* ... */
}
```

The above takes advantage of the fact that enum member fields are in the global namespace, so the values will exist, and since they can fit in an unsigned char, the code will work through the typedef.

All of the above is required because C++98/03 doesn't have support for enum base types.

I have the following question: Can we use C++11 or would that break GDC / LDC? With C++11 we could use `enum class` which would solve this nicely. The issue with `enum class` is that it will break code since not the fields need to be prefixed with the enum name.

But still, what do you think? What are the pros and cons of supporting/using C++11?

July 17, 2019
On Wednesday, 17 July 2019 at 13:35:35 UTC, Iain Buclaw wrote:
>
> But apart from the construction (and possible destruction) of all frontend types, there shouldn't be anything duplicated.
>
> Did you consider cross compiler generation?

Motivations for doing it inside DMD instead of a separate library:

- DMD frontend isn't stable (AST nodes are often changed)
- DMD frontend isn't SemVer-tagged (so you can only rely on ~master)
- people expressed a lot of interest in this being integrated directly
- easier bootstrapping (though not really a concern if we require the generated headers to be checked into the dmd repository)
July 17, 2019
On Wed, 17 Jul 2019 at 15:50, Seb via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Wednesday, 17 July 2019 at 13:35:35 UTC, Iain Buclaw wrote:
> >
> > But apart from the construction (and possible destruction) of all frontend types, there shouldn't be anything duplicated.
> >
> > Did you consider cross compiler generation?
>
> Motivations for doing it inside DMD instead of a separate library:
>
> - DMD frontend isn't stable (AST nodes are often changed)
> - DMD frontend isn't SemVer-tagged (so you can only rely on
> ~master)
> - people expressed a lot of interest in this being integrated
> directly
> - easier bootstrapping (though not really a concern if we require
> the generated headers to be checked into the dmd repository)

It doesn't make bootstrapping easier, as you will be starting from a
base where either:
1. There is no D compiler
2. The D compiler does not understand -HC

Having a standalone application means you only need to worry about (1) in order to be able to generate headers to then build the D compiler.

-- 
Iain
July 17, 2019
On Wed, 17 Jul 2019 at 15:40, Eduard Staniloiu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>
> I have the following question: Can we use C++11 or would that break GDC / LDC? With C++11 we could use `enum class` which would solve this nicely. The issue with `enum class` is that it will break code since not the fields need to be prefixed with the enum name.
>
> But still, what do you think? What are the pros and cons of supporting/using C++11?
>

No you cannot use C++11, yes it will break GDC bootstrap.

-- 
Iain