Skip to content

Conversation

@jacob-carlborg
Copy link
Contributor

This allows to override the mangling of a type in an alias declaration as follows:

pragma(mangle, "foo") alias foo = int;
static assert(foo.mangleof == "foo");
static assert(int.mangleof == "i");

Overriding the mangling of a type in an alias allows for more generic solution to get the correct mangling of c_long/c_ulong for C++ functions. With the current solution the compiler is looking for a struct with the name __c_long/__c_ulong and special cases the mangling for that particular struct. Since D doesn't have implicit conversions to structs one are also forced cast/explicitly construct a __c_long struct when calling a function which uses the __c_long type as a parameter. With an alias that's not necessary anymore.

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @jacob-carlborg! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.

Some tips to help speed things up:

  • smaller, focused PRs are easier to review than big ones

  • try not to mix up refactoring or style changes with bug fixes or feature enhancements

  • provide helpful commit messages explaining the rationale behind each change

Bear in mind that large or tricky changes may require multiple rounds of review and revision.

Please see CONTRIBUTING.md for more information.

Bugzilla references

Auto-close Bugzilla Description
18095 Add support for pragma(mangle) on alias declarations

Copy link
Contributor

@RazvanN7 RazvanN7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the change in the backend related to this PR?

Later edit: Oh, I see, nevermind.

@("basic type")
{
@("override mangling")
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of all of these @("some string") UDAs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It adds a description to each test indicating what is tested. If you don't like it I can remove it. I think it adds value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see where those descriptions are being used anywhere. How is this different from just adding a comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They could be used in the future and they allow me to add a form of scope for the description.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think until we have something in our infrastructure that makes use of these descriptions, they're a bit of a distraction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine 😞. I'll remove or move them to comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that now it's much more difficult to see which code belongs to which test and which description belongs to which test. In any other D project I would have used a separate unit test block for each test, but the DMD tests are not using unit test blocks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can easily resolve that with some kind of comment header...

/*******************************************************
*  Section 1
*******************************************************/

// Section 1.1

// Section 1.2

/*******************************************************
* Section 2
*******************************************************/

// Section 2.1

// Section 2.2

... or something along those lines

FWIW, I see the value in what you were proposing, but I don't think this PR is the right place to introduce such idioms into the code base unless it solves a specific problem that we're currently facing and/or has broader support/adoption.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it solves specific problem we have but nobody else seems to agree with me.

@rainers
Copy link
Member

rainers commented Dec 26, 2017

I like the idea and also tried to implement it when Walter introduced those special structs that don't work well without implicit conversions.

I suspect it's not so easy, though. Doesn't this reintroduce some kind of "typedef", i.e. types are compared according to their mangling so the type with mangle overwrite is no longer the same as the aliased type?

pragma(mangle, "foo") alias a = int;
static assert(is(a == int));

Could you also add a test case where the mangle override is at some intermediate step?

alias a = int;
pragma(mangle, "3foo") alias b = a;
alias c = b;
c x;
static assert(x.mangle == "_D4test1x3foo");

@jacob-carlborg
Copy link
Contributor Author

@rainers Done.

@jacob-carlborg
Copy link
Contributor Author

I need to add a test for C++ mangling as well.

@jacob-carlborg
Copy link
Contributor Author

Do we have any tests for the mangling in the actual binary? .mangleof has a slightly different implementation.

@jacob-carlborg
Copy link
Contributor Author

Added tests for C++ mangling as well.

@jacob-carlborg jacob-carlborg force-pushed the 18095-alias-mangle branch 2 times, most recently from 2fe5fe0 to 41f6e94 Compare December 27, 2017 13:59
@jacob-carlborg
Copy link
Contributor Author

I suspect it's not so easy, though. Doesn't this reintroduce some kind of "typedef", i.e. types are compared according to their mangling so the type with mangle overwrite is no longer the same as the aliased type?

@rainers I added a new field to the Type base class, mangleOverride, which is not used for anything but the mangled name. It's not used in any comparison of types. So no, this is not a new kind of typedef and aliases to the same type with different mangling will be considered the same type.

@jacob-carlborg
Copy link
Contributor Author

Can we move forward with this?

@rainers
Copy link
Member

rainers commented Dec 29, 2017

I added a new field to the Type base class, mangleOverride, which is not used for anything but the mangled name.

I noticed, but Type.merge() uses the mangling to fold multiple types into one. I'm not sure this isn't used somewhere else. It even makes the definition of what actually is an identical type non-obvious: Can a function with a different mangling have the same type?

Can we move forward with this?

I guess it needs approval by @WalterBright or @andralex . A good example to show the merits would be to implement c_long et al. with this.

@jacob-carlborg
Copy link
Contributor Author

I noticed, but Type.merge() uses the mangling to fold multiple types into one. I'm not sure this isn't used somewhere else.

I'm not sure I understand. I added a new field so I know it's not used anywhere else.

It even makes the definition of what actually is an identical type non-obvious: Can a function with a different mangling have the same type?

I don't understand this question either. It's already possible today to manually set the mangling of a function.

@rainers
Copy link
Member

rainers commented Dec 29, 2017

I'm not sure I understand. I added a new field so I know it's not used anywhere else.

Check the implementation of Type.merge(): two types is considered the same if they have the same mangling, i.e. a Type object is thrown away if another identical Type object already exists. Does this imply that types are different if their mangling differs?

Example:

pragma(mangle, "3foo") alias foo = int;
void fun1(int x);
void fun2(foo x);
void call1(void function(int));
void call2(void function(foo));

void main()
{
   call1(&foo2);
   call2(&foo1);
}

Does this still work? Are the function still compatible although the mangling of the type is different? It might be ok because checks for implicit conversions are satisfied.

It's already possible today to manually set the mangling of a function.

Yes, but not the mangling of its type.

@jacob-carlborg
Copy link
Contributor Author

Does this still work? Are the function still compatible although the mangling of the type is different? It might be ok because checks for implicit conversions are satisfied.

@rainers the above works, but the following fails:

static assert(is(void function(int) == void function(foo)))

I'll have a look to see if I can figure something out.

This allows to override the mangling of a type in an alias
declaration as follows:

```d
pragma(mangle, "foo") alias foo = int;
static assert(foo.mangleof == "foo");
static assert(int.mangleof == "i");
```

Overriding the mangling of a type in an alias allows for more generic
solution to get the correct mangling of `c_long/c_ulong` for C++
functions. With the current solution the compiler is looking for a
struct with the name `__c_long/__c_ulong` and special cases the
mangling for that particular struct. Since D doesn't have implicit
conversions to structs one are also forced cast/explicitly construct a
`__c_long` struct when calling a function which uses the `__c_long`
type as a parameter. With an alias that's not necessary anymore.
@andralex
Copy link
Member

status?

@jacob-carlborg
Copy link
Contributor Author

@andralex the status is that it wasn't so easy to implement as I thought it would be. Currently I'm not working on this. The issue is, as Rainer pointed out, that the mangling is used for type comparison as well. An alias with pragma(mangle) is not intended to introduce a new type.

@JinShil
Copy link
Contributor

JinShil commented Feb 16, 2018

I suggest this be closed if it's not being actively pursued. Any objections?

@wilzbach
Copy link
Contributor

FWIW this would have been really helpful for #7893 (comment) where we can't do alias string = immutable(char)[], because the compiler doesn't know how to mangle immutable to C++.

@jacob-carlborg
Copy link
Contributor Author

FWIW this would have been really helpful for #7893 (comment) where we can't do alias string = immutable(char)[], because the compiler doesn't know how to mangle immutable to C++.

Yes, but I haven't come up with a way to solve the type comparison problem that Rainer mentioned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants