www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Need DMD AST expertise

reply Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
Context:

I'm working on a more correct implementation of the C++ name 
mangling for Linux/OSX. This is needed for the integration with 
C++/STL.

------------------------------------------------------------

Problem 1:
----------
In the following D code 'Expression' is a D class, 'foo' is a C++ 
function, its argument must be mangled as a pointer to Expression 
because D has reference semantic (whereas C++ has value semantic).

 class Expression;
 extern(C++) void foo(Expression);
Question: --------- - How to I get the linkage for Expression from a FunDeclaration? This will ensure the added indirection is put only for the D classes, not the C++ ones. I tried looking at Parameter, ClassDeclaration or TypeClass but couldn't find it. ------------------------------------------------------------ Problem 2: ---------- Template arguments that are of basic types are mangled in a special way which requires to understand which 'int' is which.
 extern(C++) A foo(A, B)(B, A, B);
 static assert(foo!(int,int).mangleof == 
 "_Z3fooIiiET_T0_S0_S1_");
In the example above the first 'int' is not the same as the second one, it's a distinct substitution. Question: --------- - How can I know which is which since from the AST perspective, the FunDeclaration's Parameters are just TypeBasic 'int'? ------------------------------------------------------------ Thx in advance!
Jun 20 2016
next sibling parent reply Johan Engelen <j j.nl> writes:
On Monday, 20 June 2016 at 12:33:31 UTC, Guillaume Chatelet wrote:
 class Expression;
 extern(C++) void foo(Expression);
Question: --------- - How to I get the linkage for Expression from a FunDeclaration? This will ensure the added indirection is put only for the D classes, not the C++ ones. I tried looking at Parameter, ClassDeclaration or TypeClass but couldn't find it.
A FuncDeclaration is a Declaration, which contains the field `LINK linkage;`. That's the one you want. -Johan
Jun 20 2016
parent reply Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
On Monday, 20 June 2016 at 13:50:45 UTC, Johan Engelen wrote:
 On Monday, 20 June 2016 at 12:33:31 UTC, Guillaume Chatelet 
 wrote:
 class Expression;
 extern(C++) void foo(Expression);
Question: --------- - How to I get the linkage for Expression from a FunDeclaration? This will ensure the added indirection is put only for the D classes, not the C++ ones. I tried looking at Parameter, ClassDeclaration or TypeClass but couldn't find it.
A FuncDeclaration is a Declaration, which contains the field `LINK linkage;`. That's the one you want. -Johan
Thx Johan. I'm confused though: `FuncDeclaration.linkage` is the linkage for the function (which I already know is C++ function since I'm mangling it) but I need the linkage for the Parameter. Parameter has a Type but I can't get the linkage from here. What did I miss?
Jun 20 2016
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-06-20 16:06, Guillaume Chatelet wrote:

 Thx Johan. I'm confused though: `FuncDeclaration.linkage` is the linkage
 for the function (which I already know is C++ function since I'm
 mangling it) but I need the linkage for the Parameter. Parameter has a
 Type but I can't get the linkage from here. What did I miss?
1. Check if the type is a class. There's a field "ty" in Type 2. If it's a class, cast it to TypeClass 3. TypeClass has a field "sym" of type ClassDeclaration 4. ClassDeclaration has three fields: "com", "cpp" and "objc". I think these fields indicate if the class declaration has extern(C++), extern(Objective-C) and so on. If none of them are true, it's standard extern(D) -- /Jacob Carlborg
Jun 20 2016
parent Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
On Monday, 20 June 2016 at 14:42:22 UTC, Jacob Carlborg wrote:
 On 2016-06-20 16:06, Guillaume Chatelet wrote:

 Thx Johan. I'm confused though: `FuncDeclaration.linkage` is 
 the linkage
 for the function (which I already know is C++ function since 
 I'm
 mangling it) but I need the linkage for the Parameter. 
 Parameter has a
 Type but I can't get the linkage from here. What did I miss?
1. Check if the type is a class. There's a field "ty" in Type 2. If it's a class, cast it to TypeClass 3. TypeClass has a field "sym" of type ClassDeclaration 4. ClassDeclaration has three fields: "com", "cpp" and "objc". I think these fields indicate if the class declaration has extern(C++), extern(Objective-C) and so on. If none of them are true, it's standard extern(D)
Pretty cool. Thx Jacob! Anyone has a suggestion for my second problem? If not I'll have to do some kind of mapping between the template args and the parameters...
Jun 20 2016
prev sibling parent Johan Engelen <j j.nl> writes:
On Monday, 20 June 2016 at 14:06:57 UTC, Guillaume Chatelet wrote:
 
 Thx Johan. I'm confused though
Sorry for misreading your question.
Jun 20 2016
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-06-20 14:33, Guillaume Chatelet wrote:

 Problem 2:
 ----------
 Template arguments that are of basic types are mangled in a special way
 which requires to understand which 'int' is which.

 extern(C++) A foo(A, B)(B, A, B);
 static assert(foo!(int,int).mangleof == "_Z3fooIiiET_T0_S0_S1_");
In the example above the first 'int' is not the same as the second one, it's a distinct substitution. Question: --------- - How can I know which is which since from the AST perspective, the FunDeclaration's Parameters are just TypeBasic 'int'? ------------------------------------------------------------
Not sure I understand the question. Are you saying that the two integers are mangled differently because there are two template parameters? I'm guessing you need to look at the template declaration to get more information about the template parameters. -- /Jacob Carlborg
Jun 20 2016
parent reply Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
On Monday, 20 June 2016 at 18:59:09 UTC, Jacob Carlborg wrote:
 On 2016-06-20 14:33, Guillaume Chatelet wrote:

 Problem 2:
 ----------
 Template arguments that are of basic types are mangled in a 
 special way
 which requires to understand which 'int' is which.

 extern(C++) A foo(A, B)(B, A, B);
 static assert(foo!(int,int).mangleof == 
 "_Z3fooIiiET_T0_S0_S1_");
In the example above the first 'int' is not the same as the second one, it's a distinct substitution. Question: --------- - How can I know which is which since from the AST perspective, the FunDeclaration's Parameters are just TypeBasic 'int'? ------------------------------------------------------------
Not sure I understand the question.
Sorry about not being too clear.
 Are you saying that the two integers are mangled differently 
 because there are two template parameters?
Yes exactly.
 I'm guessing you need to look at the template declaration to 
 get more information about the template parameters.
The TemplateInstance [1] gives me `tiargs` and `tdtypes`. // Array of Types/Expressions of template // instance arguments [int*, char, 10*10] Objects* tiargs; // Array of Types/Expressions corresponding // to TemplateDeclaration.parameters // [int, char, 100] Objects tdtypes; I'm using `tiargs` right now (I'm not really sure what `tdtypes` is). AFAIU I can access TemplateDeclaration from TemplateInstance through `tempdecl` even though it's stored as a Dsymbol. I'll have a look at `parameters` from TemplateDeclaration [2] but I still need to match it to the function arguments somehow. The following example illustrates the process of pairing the int to the template parameter. extern(C++) B foo(A, B)(*B, ref const A); foo!(int, int) => int foo(*int, ref const int); ^ ^ ^ ^ ^ 1 2 2 1 2 1. https://github.com/dlang/dmd/blob/master/src/dtemplate.d#L5895 2. https://github.com/dlang/dmd/blob/master/src/dtemplate.d#L406
Jun 20 2016
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-06-20 22:52, Guillaume Chatelet wrote:

 The TemplateInstance [1] gives me `tiargs` and `tdtypes`.

     // Array of Types/Expressions of template
     // instance arguments [int*, char, 10*10]
     Objects* tiargs;

     // Array of Types/Expressions corresponding
     // to TemplateDeclaration.parameters
     // [int, char, 100]
     Objects tdtypes;

 I'm using `tiargs` right now (I'm not really sure what `tdtypes` is).
A guess: "tiargs" is the types of the values passed to the template. "tdtypes" is the types the template is instantiated with. void foo(T)(T* a); int b; foo!(int)(&b*); "tiargs" is "int*" and "tdtypes" is "int". But this can easily be confirmed using some printf debugging.
 AFAIU I can access TemplateDeclaration from TemplateInstance through
 `tempdecl` even though it's stored as a Dsymbol.

 I'll have a look at `parameters` from TemplateDeclaration [2] but I
 still need to match it to the function arguments somehow. The following
 example illustrates the process of pairing the int to the template
 parameter.

     extern(C++) B foo(A, B)(*B, ref const A);

     foo!(int, int) => int foo(*int, ref const int);
           ^    ^       ^        ^              ^
           1    2       2        1              2

 1. https://github.com/dlang/dmd/blob/master/src/dtemplate.d#L5895
 2. https://github.com/dlang/dmd/blob/master/src/dtemplate.d#L406
Are the types the same objects so you can compare by just comparing the pointers? -- /Jacob Carlborg
Jun 20 2016
parent reply Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
On Tuesday, 21 June 2016 at 06:25:26 UTC, Jacob Carlborg wrote:
 On 2016-06-20 22:52, Guillaume Chatelet wrote:

 [...]
A guess: "tiargs" is the types of the values passed to the template. "tdtypes" is the types the template is instantiated with. void foo(T)(T* a); int b; foo!(int)(&b*); "tiargs" is "int*" and "tdtypes" is "int". But this can easily be confirmed using some printf debugging.
 [...]
Are the types the same objects so you can compare by just comparing the pointers?
AFAIK basic types are instantiated once and reused: https://github.com/dlang/dmd/blob/b67694a0d74437d3a1581da2b9f1b785dc7b3c88/src/mtype.d#L861 So comparing pointers wouldn't work.
Jun 21 2016
parent reply Jacob Carlborg <doob me.com> writes:
On 2016-06-21 09:45, Guillaume Chatelet wrote:

 AFAIK basic types are instantiated once and reused:
 https://github.com/dlang/dmd/blob/b67694a0d74437d3a1581da2b9f1b785dc7b3c88/src/mtype.d#L861


 So comparing pointers wouldn't work.
Yeah. I'm just guessing here :). Sorry, I don't think I can help you. -- /Jacob Carlborg
Jun 21 2016
parent Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
On Tuesday, 21 June 2016 at 09:13:26 UTC, Jacob Carlborg wrote:
 On 2016-06-21 09:45, Guillaume Chatelet wrote:

 AFAIK basic types are instantiated once and reused:
 https://github.com/dlang/dmd/blob/b67694a0d74437d3a1581da2b9f1b785dc7b3c88/src/mtype.d#L861


 So comparing pointers wouldn't work.
Yeah. I'm just guessing here :). Sorry, I don't think I can help you.
Thx anyways! I'll continue my journey [1] :) 1. https://cdn.meme.am/instances/39916320.jpg
Jun 21 2016
prev sibling parent reply Elie Morisse <syniurge gmail.com> writes:
On Monday, 20 June 2016 at 20:52:02 UTC, Guillaume Chatelet wrote:
 I'll have a look at `parameters` from TemplateDeclaration [2] 
 but I still need to match it to the function arguments somehow.
The templated function is the child symbol of the TemplateDeclaration which shares the same name i.e Dsymbol* s; Dsymbol.oneMembers(tempdecl->members, &s, tempdecl->ident); auto fd = cast(FuncDeclaration) s; You then need to visit the templated function parameters « (cast(TypeFunction) fd->type)->parameters » and look for identifiers that match the TemplateDeclaration.parameters[].ident. In the simplest cases the types of templated function parameters are TypeIdentifier.
Jun 21 2016
next sibling parent Elie Morisse <syniurge gmail.com> writes:
On Tuesday, 21 June 2016 at 19:42:54 UTC, Elie Morisse wrote:
 On Monday, 20 June 2016 at 20:52:02 UTC, Guillaume Chatelet 
 wrote:
 « (cast(TypeFunction) fd->type)->parameters »
Mixing C++ and D once more..
Jun 21 2016
prev sibling parent Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
On Tuesday, 21 June 2016 at 19:42:54 UTC, Elie Morisse wrote:
 On Monday, 20 June 2016 at 20:52:02 UTC, Guillaume Chatelet 
 wrote:
 [...]
The templated function is the child symbol of the TemplateDeclaration which shares the same name i.e [...]
Thx Elie! It helps :) I came up with this quick and dirty piece of code to get the parameters from the template declaration and the function declaration: code:
 auto declaration = 
 cast(TemplateDeclaration)templateInstance.tempdecl;
 assert(declaration);
 printf("TemplateDeclaration %x\n", declaration);
 foreach(parameter; *declaration.parameters) {
     printf("Parameter %s\n", parameter.ident.toChars());
 }
 
 if (declaration.onemember) {
     FuncDeclaration fd = 
 declaration.onemember.isFuncDeclaration();
     if (fd && fd.type) {
         TypeFunction tf = cast(TypeFunction)fd.type;
         assert(tf);
         printf("TypeFunction %x\n", tf);
         if(tf.next) printf("Parameter return %s\n", 
 tf.next.toChars());
         if(tf.parameters) foreach(parameter; *tf.parameters) {
             printf("Parameter %s\n", parameter.type.toChars());
         }
     }
 }
input:
 extern(C++) C foo(A, B, C)(B, A);
output:
 TemplateDeclaration 764f76b0
 Parameter A
 Parameter B
 Parameter C
 TypeFunction 764f7370
 Parameter return C
 Parameter B
 Parameter A
It works as expected. I still need to do the mapping and handle subtleties like this but I'm on the right track.
 extern(C++) ref C foo(A, B, C)(B*, const(A)*);
Thx!
Jun 21 2016