www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - POD

reply Aleksey S. Skidan <al.skidan gmail.com> writes:
I just wonder if there's such a thing as POD type in D? I have failed to find
one. The extern(C) struct seems not to be the thing because it is hardwired to
the ABI.
Dec 29 2006
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Aleksey S. Skidan wrote:
 I just wonder if there's such a thing as POD type in D? I have failed to find
 one. The extern(C) struct seems not to be the thing because it is hardwired to
 the ABI.
Basic types and structs are POD (plain old data). Unless you're referring to a different kind of POD.
Dec 29 2006
parent reply Aleksey S. Skidan <al.skidan gmail.com> writes:
== Quote from Hasan Aljudy (hasan.aljudy gmail.com)'s article
 Aleksey S. Skidan wrote:
 I just wonder if there's such a thing as POD type in D? I have failed to find
 one. The extern(C) struct seems not to be the thing because it is hardwired to
 the ABI.
Basic types and structs are POD (plain old data). Unless you're referring to a different kind of POD.
Great thanks, but I do know what POD is. But unfortunately D's structs are not POD types. They depend on TypeInfo. For ex.: module blah; struct Foo{ int a; } static Foo bar = { 3; }; Then $ dmd -c blah.d $ objdump -t blah.o And you'll see a section named like .gnu.linkonce.d.*__initZ that contains the bar. But this section contains a reference to TypeInfo object for the Foo.
Dec 29 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
Aleksey S. Skidan wrote:
 == Quote from Hasan Aljudy (hasan.aljudy gmail.com)'s article
 Aleksey S. Skidan wrote:
 I just wonder if there's such a thing as POD type in D? I have failed to find
 one. The extern(C) struct seems not to be the thing because it is hardwired to
 the ABI.
Basic types and structs are POD (plain old data). Unless you're referring to a different kind of POD.
Great thanks, but I do know what POD is. But unfortunately D's structs are not POD types. They depend on TypeInfo. For ex.: module blah; struct Foo{ int a; } static Foo bar = { 3; }; Then $ dmd -c blah.d $ objdump -t blah.o And you'll see a section named like .gnu.linkonce.d.*__initZ that contains the bar. But this section contains a reference to TypeInfo object for the Foo.
Sure, but the TypeInfo doesn't affect the size or layout of Foo. Sean
Dec 29 2006
prev sibling next sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Aleksey S. Skidan wrote:
 But unfortunately D's structs are not POD
 types. They depend on TypeInfo. For ex.:
 
 module blah;
 struct Foo{ int a; }
 static Foo bar = { 3; };
 
 Then
 $ dmd -c blah.d
 $ objdump -t blah.o
 
 And you'll see a section named like .gnu.linkonce.d.*__initZ that contains the
 bar. But this section contains a reference to TypeInfo object for the Foo.
So? That doesn't have anything to do with POD-ness. [after removing the extra ; in the initializer] Actually, I don't see any such thing in my object file: -------------------- $ objdump -sr test.o # show relocation records and section contents test.o: file format elf32-i386 RELOCATION RECORDS FOR [.text]: (none) RELOCATION RECORDS FOR [.data]: (none) RELOCATION RECORDS FOR [.gnu.linkonce.d._D19TypeInfo_S4blah3Foo6__initZ]: OFFSET TYPE VALUE 00000000 R_386_32 _D15TypeInfo_Struct6__vtblZ 0000000c R_386_32 .rodata Contents of section .data: 0000 03000000 .... Contents of section .rodata: 0000 626c6168 2e466f6f 00000000 00000000 blah.Foo........ Contents of section .gnu.linkonce.d._D19TypeInfo_S4blah3Foo6__initZ: 0000 00000000 00000000 08000000 00000000 ................ 0010 04000000 00000000 00000000 00000000 ................ 0020 00000000 00000000 ........ -------------------- I don't see any special section for 'bar' at all (unless you count .data, which happens to only contain 'bar', already initialized to 3). The only references to TypeInfo I see are the TypeInfo for Foo (not bar) and a relocation record that fills in the vtable pointer for TypeInfo_Struct. The TypeInfo is probably emitted in this object file to avoid having to potentially emit it everywhere it's used. If nothing actually uses it in this program, the linker should be able to throw it out. IIRC optlink does this automatically on Windows, but on Linux you need to pass -L--gc-sections to DMD to get ld to do this.
Dec 29 2006
parent reply Aleksey S. Skidan <al.skidan gmail.com> writes:
What it's all about is that I wanted to port my kernel from C++ into D. With C++
it's an easy task. Just turn off ABI-dependent stuff. With D it's not that
story.
I can't turn off RTTI for ex. Thus I can't compile my kernel not implementing
object.d from ABI. And that's not good. I don't want to have extra needless data
in my data section. The data I will never use!
Dec 29 2006
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Aleksey S. Skidan wrote:
 What it's all about is that I wanted to port my kernel from C++ into D. With
C++
 it's an easy task. Just turn off ABI-dependent stuff. With D it's not that
story.
 I can't turn off RTTI for ex. Thus I can't compile my kernel not implementing
 object.d from ABI. And that's not good. I don't want to have extra needless
data
 in my data section. The data I will never use!
As I've said before, object.d isn't hard to port. The version for my kernel has minimal modifications. If you're using ld, just pass --gc-sections on the command line to remove unreferenced data and code[1]... [1]: Caveat: you may need to modify your linker script to use KEEP() around sections containing any multiboot headers or other things not referenced directly from the code, to make sure they don't get thrown away. That includes .ctor* and .dtor* sections, if you use static this(), static ~this() or unittest{} blocks in your code and expect the ModuleInfo linked list with their info to be built like in Phobos on Linux.
Dec 29 2006
parent reply Aleksey S. Skidan <al.skidan gmail.com> writes:
== Quote from Frits van Bommel (fvbommel REMwOVExCAPSs.nl)'s article
 Aleksey S. Skidan wrote:
 What it's all about is that I wanted to port my kernel from C++ into D. With
C++
 it's an easy task. Just turn off ABI-dependent stuff. With D it's not that
story.
 I can't turn off RTTI for ex. Thus I can't compile my kernel not implementing
 object.d from ABI. And that's not good. I don't want to have extra needless
data
 in my data section. The data I will never use!
As I've said before, object.d isn't hard to port. The version for my kernel has minimal modifications. If you're using ld, just pass --gc-sections on the command line to remove unreferenced data and code[1]... [1]: Caveat: you may need to modify your linker script to use KEEP() around sections containing any multiboot headers or other things not referenced directly from the code, to make sure they don't get thrown away. That includes .ctor* and .dtor* sections, if you use static this(), static ~this() or unittest{} blocks in your code and expect the ModuleInfo linked list with their info to be built like in Phobos on Linux.
Great thanks I'll try it. Though IMHO it's not a convinient way (more C-lysh is more convinient as for me [the KISS rule]). But as the language is young...
Dec 29 2006
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/29/2006 12:48 PM, Aleksey S. Skidan wrote:
 Great thanks I'll try it. Though IMHO it's not a convinient way (more C-lysh is
 more convinient as for me [the KISS rule]).
 But as the language is young...
Another way, if you're feeling adventurous, is to write a program to read the .o files and remove those sections. It's not hard, but if you're not comfortable with the .o file format, it can be a bit daunting.
Dec 28 2012
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Aleksey S. Skidan:

 Great thanks, but I do know what POD is. But unfortunately D's 
 structs are not POD
 types. They depend on TypeInfo. For ex.:
In LDC there are pragmas to disable specific typeinfos/moduleinfos: http://wiki.dlang.org/LDC-specific_language_changes#LDC_no_typeinfo Bye, bearophile
Dec 19 2012
prev sibling next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Aleksey S. Skidan wrote:

 I just wonder if there's such a thing as POD type in D? I have failed to
 find one. The extern(C) struct seems not to be the thing because it is
 hardwired to the ABI.
http://www.digitalmars.com/d/glossary.html#pod -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Dec 29 2006
prev sibling next sibling parent reply "Red" <resmith lavabit.com> writes:
I am learning D and reading the Kindle spec. It says:

"In C++ parlance, a D struct is a POD (Plain Old Data) type" with
a trivial constructors and destructors".

<POD (Plain Old Data)> is a link. Clinking on it leads to this
definition at dlang.org:

"Refers to a struct that contains no hidden members, does not
have virtual functions, does not inherit, has no destructor, and
can be initialized and copied via simple bit copies. D structs
are POD."

The definition says no destructor and no hidden members. Whereas
above it says that a D struct has a (trivial) destructors.

And below that in the spec there is a table which has a row for
"hidden members". It shows that a D struct has hidden members.

Not a major issue of course, but I am just wondering why the
definition of POD says "no destructor" and "no hidden members"
whereas a D struct has both and is referred to as POD.
Dec 19 2012
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, December 20, 2012 04:31:05 Red wrote:
 Not a major issue of course, but I am just wondering why the
 definition of POD says "no destructor" and "no hidden members"
 whereas a D struct has both and is referred to as POD.
D structs really aren't necessarily PODs. They can be used as PODs, but they don't have to be. A POD is basically a C struct which just holds data. D structs are nearly identical to C classes except for the fact that they can't have inheritance. They can have functions, destructors data hiding, etc., in which case they aren't POD types at all. The D docs should probably be changed. - Jonathan M Davis
Dec 19 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/20/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 They can have functions.. in
 which case they aren't POD types at all.
Having regular functions doesn't change the state of PODs. Having a ctor/dtor/postblit probably does though (you can no longer safely do a memcpy). But AFAIK you can always rely on the field layout of a non-nested D struct, so a D struct should mostly remain compatible to C structs.
Dec 20 2012
parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Thursday, 20 December 2012 at 10:57:08 UTC, Andrej Mitrovic 
wrote:
 On 12/20/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 They can have functions.. in
 which case they aren't POD types at all.
Having regular functions doesn't change the state of PODs. Having a ctor/dtor/postblit probably does though (you can no longer safely do a memcpy).
How presence of ctor/dtor/postblit affect the POD (in a sense of changing structure size and alignment)?
 But AFAIK you can always rely on the field layout of a 
 non-nested D
 struct, so a D struct should mostly remain compatible to C 
 structs.
Agree, unless it is a non-static nested function struct which has hidden member.
Dec 20 2012
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/20/12, Maxim Fomin <maxim maxim-fomin.ru> wrote:
 How presence of ctor/dtor/postblit affect the POD (in a sense of
 changing structure size and alignment)?
It doesn't, but the semantics are different. For example if you pass your struct to the C side the C code might do copies of your struct but it will have no idea about your postblits or destructors.
Dec 20 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/20/2012 4:12 AM, Andrej Mitrovic wrote:
 On 12/20/12, Maxim Fomin <maxim maxim-fomin.ru> wrote:
 How presence of ctor/dtor/postblit affect the POD (in a sense of
 changing structure size and alignment)?
It doesn't, but the semantics are different. For example if you pass your struct to the C side the C code might do copies of your struct but it will have no idea about your postblits or destructors.
There's more than that. POD structs can exist solely in registers. Having ctor/dtor/postblit means that structs cannot be enregistered, because those operations require a pointer to the instance. There are subtleties to it. It affects all kinds of things like ABI call/return issues, varargs, etc. There needs to be an easy way to query a type to see if it is POD, and currently there isn't one.
Dec 28 2012
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/28/12, Walter Bright <newshound2 digitalmars.com> wrote:
 There needs to be an easy way to query a type to see if it is POD, and
 currently there isn't one.
I suggest we implement a compiler trait via __traits(isPOD, Type). C++11 has is_pod, D should have a Phobos template that wraps around the new trait. C++03/11 also define their meaning of PODs to allow interfacing with C. C++03 rules: http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176#4178176 and C++11 rules: http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/7189821#7189821 According to that function you gave access specifiers in D do not change the meaning of PODs (unlike in C++), but other than that the rules are very similar. What about field initalizers though? Can their presence make the default-generated struct constructor non-trivial in D, or does it not matter? E.g. in C++11: struct NotAggregate { int x = 5; // OK std::vector<int> s{1,2,3}; // makes it a non-aggregate, therefore non-POD }; I'm not sure if D has these sort of issues.
Dec 28 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-12-29 00:53, Andrej Mitrovic wrote:

 I suggest we implement a compiler trait via __traits(isPOD, Type).
 C++11 has is_pod, D should have a Phobos template that wraps around
 the new trait.
Do we need a new trait, can't this be done in pure D? -- /Jacob Carlborg
Dec 29 2012
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/29/12, Jacob Carlborg <doob me.com> wrote:
 Do we need a new trait, can't this be done in pure D?
It can, but it's simpler to do in the compiler as it already has an isPod() function.
Dec 29 2012
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/29/2012 4:38 AM, Jacob Carlborg wrote:
 On 2012-12-29 00:53, Andrej Mitrovic wrote:

 I suggest we implement a compiler trait via __traits(isPOD, Type).
 C++11 has is_pod, D should have a Phobos template that wraps around
 the new trait.
Do we need a new trait, can't this be done in pure D?
Yes for a new trait, for the reasons: 1. POD status is affected by a number of characteristics. This would all have to be rather carefully done to ensure an exact match with the compiler. 2. There are many discussions here about changing the definition of POD. The likelihood of changing the compiler, and then neglecting to change the Phobos version or not updating the Phobos version correctly is high.
Dec 29 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/28/12, Walter Bright <newshound2 digitalmars.com> wrote:
 There's more than that. POD structs can exist solely in registers. Having
 ctor/dtor/postblit means that structs cannot be enregistered, because those
 operations require a pointer to the instance.

 There are subtleties to it. It affects all kinds of things like ABI
 call/return issues, varargs, etc.
These are good points and reminds us that we need to update the documentation, there's a section that reads: "In C++ parlance, a D struct is a POD (Plain Old Data) type, with trivial constructors and destructors." It needs further explanation. Just a few weeks ago someone tried to add a non-trivial constructor in a D struct which interfaces with C and his code stopped working, these are likely the reasons why.
Dec 28 2012
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/19/2012 7:31 PM, Red wrote:
 The definition says no destructor and no hidden members. Whereas
 above it says that a D struct has a (trivial) destructors.
A "trivial" destructor is the implicit one that does nothing, i.e. it means no destructor.
Dec 28 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/29/2006 5:41 AM, Aleksey S. Skidan wrote:
 I just wonder if there's such a thing as POD type in D? I have failed to find
 one. The extern(C) struct seems not to be the thing because it is hardwired to
 the ABI.
D's definition of POD: /*************************************** * Return true if struct is POD (Plain Old Data). * This is defined as: * not nested * no postblits, constructors, destructors, or assignment operators * no fields with with any of those * The idea being these are compatible with C structs. * * Note that D struct constructors can mean POD, since there is always default * construction with no ctor, but that interferes with OPstrpar which wants it * on the stack in memory, not in registers. */ bool StructDeclaration::isPOD() { if (isnested || cpctor || postblit || ctor || dtor) return false; /* Recursively check any fields have a constructor. * We should cache the results of this. */ for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); while (tv->ty == Tsarray) { TypeSArray *ta = (TypeSArray *)tv; tv = tv->nextOf()->toBasetype(); } if (tv->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tv; StructDeclaration *sd = ts->sym; if (!sd->isPOD()) return false; } } return true; }
Dec 28 2012
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/28/12, Walter Bright <newshound2 digitalmars.com> wrote:
 D's definition of POD:

 /***************************************
   * Return true if struct is POD (Plain Old Data).
   * This is defined as:
   *      not nested
   *      no postblits, constructors, destructors, or assignment operators
   *      no fields with with any of those
   * The idea being these are compatible with C structs.
   *
   * Note that D struct constructors can mean POD, since there is always
 default
   * construction with no ctor, but that interferes with OPstrpar which wants
 it
   * on the stack in memory, not in registers.
   */
 bool StructDeclaration::isPOD()
 {
      if (isnested || cpctor || postblit || ctor || dtor)
          return false;

      /* Recursively check any fields have a constructor.
       * We should cache the results of this.
       */
      for (size_t i = 0; i < fields.dim; i++)
      {
          Dsymbol *s = fields[i];
          VarDeclaration *v = s->isVarDeclaration();
          assert(v && v->storage_class & STCfield);
          if (v->storage_class & STCref)
              continue;
          Type *tv = v->type->toBasetype();
          while (tv->ty == Tsarray)
          {   TypeSArray *ta = (TypeSArray *)tv;
              tv = tv->nextOf()->toBasetype();
          }
          if (tv->ty == Tstruct)
          {   TypeStruct *ts = (TypeStruct *)tv;
              StructDeclaration *sd = ts->sym;
              if (!sd->isPOD())
                  return false;
          }
      }
      return true;
 }
I think there's a bug here, it never checks for the presence of opAssign. Maybe change the first if check to: if (isnested || cpctor || postblit || ctor || dtor || search_function(this, Id::assign)) I can make a pull with this fix (and add the new isPOD trait). Whaddya think?
Dec 28 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/28/2012 4:23 PM, Andrej Mitrovic wrote:
 I think there's a bug here, it never checks for the presence of
 opAssign. Maybe change the first if check to:

   if (isnested || cpctor || postblit || ctor || dtor ||
 search_function(this, Id::assign))

 I can make a pull with this fix (and add the new isPOD trait). Whaddya think?
I don't think a dependency on opAssign is necessary. I think it's great you're doing a pull request for it. The definition of POD may change slightly in the future, and it may differ on different platforms, which is why I think it is important to have a __traits for it that gets the compiler's view of what's a POD. I see you already saw: http://d.puremagic.com/issues/show_bug.cgi?id=9237
Dec 28 2012
prev sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Friday, 28 December 2012 at 22:40:13 UTC, Walter Bright wrote:
 D's definition of POD: […]
The definition of POD as used in the x86-64 System V ABI – and its implementation is really the only place where isPOD matters right now – is as follows (ver. 0.99.6): "If a C++ object has either a non-trivial copy constructor or a non-trivial destructor, it is passed by invisible reference […]." and as a footnote: "A de/constructor is trivial if it is an implicitly-declared default de/constructor and if: - its class has no virtual functions and no virtual base classes, and - all the direct base classes of its class have trivial de/constructors, and - for all the nonstatic data members of its class that are of class type (or array thereof), each such class has a trivial de/constructor." Note that the absence of a constructor is *not* required for a C++ class/struct to be considered POD under the rules of the x86-64 ABI. I would want to be *very* sure about my reasons before changing this behavior as it will definitely lead to confusion, especially considering that ABI details are black magic to many programmers anyway. In fact, I had been planning to ping you about this since I started to work on the LDC ABI implementation a few months ago (a place where this makes a difference are e.g. some types from core.time), but I then shifted my focus more towards resolving the immediate release blocker issues and apparently in turn also forgot to raise this issue on the mailing list. Anyway, I would ask you to reconsider your decision because: - It breaks the principle of least surprise regarding the C<->D mapping: While you can add adornments like constructors to the C++ definition of a given C type, you can't in D. Also, as mentioned by Andrej, as a programmer you just don't expect a constructor to make your struct somehow behave differently than a plain C struct. - More or less another way of stating the last point, it is not at all obvious from the x86-64 ABI specification: I re-implemented the x86-64 ABI for D from scratch for LDC recently, and this was just about the only difference between your implementation and mine (the other, as far as I remember, being that DMD mistakenly never enregisters 3-byte structs). Sure, we need to properly document the D behavior anyway, but if the general rule is "D follows the ABI of the host C compiler", I think we should avoid diverting from the obvious path as much as possible. - The new C++ standard defines POD structs as being "a non-union class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types)" ([class]p10), where "trivial" means no copy/move constructors or destructors, and standard-layout essentially excludes virtuals, different access control modifiers and base classes with non-static fields. In particular, POD structs are allowed to have constructors, and going a different route with D will likely be a source of confusion. - There are also possible performance implications: Structs that just wrap a single field in order to enrich it with type information, such as Duration or a Quantity struct from a units of measurement library, will likely benefit from being passed in registers (if available), even if they will probably have constructors. In fact, having such one-field structs behave like a naked value might be vitally important to be able to decorate a C API with e.g. units information (even if such code would strictly speaking be architecture dependent). As far as I can see – and I'm merely guessing based on the isPOD comment here – the only reason for not just applying the C/C++ definition in the obvious way might be a quirk in the DMD backend implementation? David
Dec 28 2012
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
David Nadlinger:

  - More or less another way of stating the last point, it is 
 not at all obvious from the x86-64 ABI specification: I 
 re-implemented the x86-64 ABI for D from scratch for LDC 
 recently, and this was just about the only difference between 
 your implementation and mine (the other, as far as I remember, 
 being that DMD mistakenly never enregisters 3-byte structs).
I have done a small experiment. This is C99 code: #include "stdint.h" typedef uint8_t ubyte; typedef struct { ubyte r, g, b; } RGB; RGB bar(RGB c1, RGB c2) { return (RGB){ (ubyte)(c1.r + c2.r), (ubyte)(c1.g + c2.g), (ubyte)(c1.g + c2.b) }; } Compiled with Clang 3.0 gives: bar: pushl %esi movl 8(%esp), %ecx movl 12(%esp), %eax leal (%eax,%ecx), %edx movzbl %dl, %esi andl $16776960, %ecx # imm = 0xFFFF00 shrl $8, %ecx andl $16777215, %eax # imm = 0xFFFFFF movl %eax, %edx shrl $16, %edx addl %ecx, %edx shll $16, %edx orl %esi, %edx shrl $8, %eax addl %ecx, %eax shll $8, %eax movzwl %ax, %eax orl %edx, %eax popl %esi ret This is D code: struct RGB { ubyte r, g, b; } RGB bar(RGB c1, RGB c2) { return RGB(cast(ubyte)(c1.r + c2.r), cast(ubyte)(c1.g + c2.g), cast(ubyte)(c1.g + c2.b)); } DMD 2.061alpha gives (-O -release -inline): _D4test3barFS4test3RGBS4test3RGBZS4test3RGB: push EAX push EBX mov EBX,EAX push ESI push EDI movzx ECX,byte ptr 018h[ESP] movzx EDX,byte ptr 014h[ESP] add CL,DL mov [EBX],CL movzx ESI,byte ptr 019h[ESP] mov ECX,ESI movzx EDI,byte ptr 015h[ESP] mov EDX,EDI mov 0Ch[ESP],ECX add CL,DL mov 1[EBX],CL mov ECX,0Ch[ESP] movzx ESI,byte ptr 016h[ESP] mov EDX,ESI add CL,DL mov 2[EBX],CL pop EDI pop ESI pop EBX pop ECX ret 8 Bye, bearophile
Dec 28 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
                   (ubyte)(c1.g + c2.b) };
Sorry, that should be (and the same in the D code):
                   (ubyte)(c1.b + c2.b) };
But it's not important, also because both versions have the same little bug. Bye, bearophile
Dec 28 2012
prev sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Saturday, 29 December 2012 at 02:41:22 UTC, bearophile wrote:
 I have done a small experiment. This is C99 code: […]
Eww, AT&T syntax… ;) I finally added a bugzilla entry for the issue, which includes a more minimal example: http://d.puremagic.com/issues/show_bug.cgi?id=9239 David
Dec 28 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/28/2012 5:53 PM, David Nadlinger wrote:
 As far as I can see – and I'm merely guessing based on the isPOD comment
here –
 the only reason for not just applying the C/C++ definition in the obvious way
 might be a quirk in the DMD backend implementation?
The idea with POD is not necessarily to be compatible with C++ POD, but to be compatible what the technical point of POD is. As I wrote on github, "Remember, a POD type can be enregistered, if it also fits in registers and the code gen supports it. A non-POD can never be enregistered. A POD type can also be bit copied around at will without regard to needing to call any functions for any part of that. (This means POD can be spilled into registers, cached in registers, stored half in registers and half in memory, etc.)" POD data must also exactly match the C version of it, otherwise, obviously, binary compatibility with C will be lost. D has no requirement to be binary compatible with C++ non-POD structs. So, as long as we satisfy those requirements, we can invent our own definition of POD in a way that makes the most sense for D. For example, C++ disallows mixed public/private data in a POD. I've never understood the reason for that restriction other than "C doesn't have private fields". D doesn't propagate that aspect. Also, you made some good points about changing the D definition of POD. That is worthy of more discussion, and serves to underscore that we need an isPOD trait that is set by the compiler, not a reinvention in the library, because when isPOD changes then user code will automatically change in step.
Dec 28 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/28/12 10:12 PM, Walter Bright wrote:
 For example, C++ disallows mixed public/private data in a POD. I've
 never understood the reason for that restriction other than "C doesn't
 have private fields". D doesn't propagate that aspect.
The idea was to leave C++ compilers to change the order of fields in classes with private data for optimal layout. I don't know of any compilers that do, but that was the intent. PODs were not susceptible to such layout optimization because they had to be compatbile with C's layout. Andrei
Dec 28 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/28/2012 7:37 PM, Andrei Alexandrescu wrote:
 On 12/28/12 10:12 PM, Walter Bright wrote:
 For example, C++ disallows mixed public/private data in a POD. I've
 never understood the reason for that restriction other than "C doesn't
 have private fields". D doesn't propagate that aspect.
The idea was to leave C++ compilers to change the order of fields in classes with private data for optimal layout. I don't know of any compilers that do, but that was the intent. PODs were not susceptible to such layout optimization because they had to be compatbile with C's layout.
I didn't know that, but it makes sense. Interestingly, D's original design allowed fields in classes to be rearranged. This kind of fell by the wayside with the align directive.
Dec 28 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Saturday, 29 December 2012 at 03:13:00 UTC, Walter Bright 
wrote:
 POD data must also exactly match the C version of it, 
 otherwise, obviously, binary compatibility with C will be lost. 
 D has no requirement to be binary compatible with C++ non-POD 
 structs.

 So, as long as we satisfy those requirements, we can invent our 
 own definition of POD in a way that makes the most sense for D.
I didn't doubt that we can invent our own definition, just that it is a good idea. ;)
 For example, C++ disallows mixed public/private data in a POD. 
 I've never understood the reason for that restriction other 
 than "C doesn't have private fields". D doesn't propagate that 
 aspect.
Yes, I don't understand that one as well – hm, maybe in order to allow the compiler to optimize the layout?
 Also, you made some good points about changing the D definition 
 of POD. That is worthy of more discussion, and serves to 
 underscore that we need an isPOD trait that is set by the 
 compiler, not a reinvention in the library, because when isPOD 
 changes then user code will automatically change in step.
Agreed – but I'm not quite sure if "plain old data" is defined (or, for that matter, used) in the language right now. Just about the only explanation given in the spec is in the glossary, which has »Refers to a struct that contains no hidden members, does not have virtual functions, does not inherit, has no destructor, and can be initialized and copied via simple bit copies.« (no mention of constructors) but then goes on to say »D structs are POD«, which is probably a remnant from D1 days. David
Dec 28 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/29/12, Walter Bright <newshound2 digitalmars.com> wrote:
 Remember, a POD type can be enregistered
This means it can be passed in registers (for anyone not aware of the term).
Dec 28 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/28/2012 8:06 PM, Andrej Mitrovic wrote:
 On 12/29/12, Walter Bright <newshound2 digitalmars.com> wrote:
 Remember, a POD type can be enregistered
This means it can be passed in registers (for anyone not aware of the term).
More than that, it means they can live entirely in registers.
Dec 28 2012
prev sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
12/29/2012 7:12 AM, Walter Bright пишет:
 On 12/28/2012 5:53 PM, David Nadlinger wrote:
 As far as I can see – and I'm merely guessing based on the isPOD
 comment here –
 the only reason for not just applying the C/C++ definition in the
 obvious way
 might be a quirk in the DMD backend implementation?
The idea with POD is not necessarily to be compatible with C++ POD, but to be compatible what the technical point of POD is. As I wrote on github, "Remember, a POD type can be enregistered, if it also fits in registers and the code gen supports it. A non-POD can never be enregistered. A POD type can also be bit copied around at will without regard to needing to call any functions for any part of that. (This means POD can be spilled into registers, cached in registers, stored half in registers and half in memory, etc.)"
I understand everything but constructors. The question is how the following is different and should we make users jump through the hoops: //non-POD? struct A { int k; this(int v) { k = v; } } vs //apparently POD? struct A { int k; static A opCall(int v) { A a; A.k = v; return a; } } Imagine that ctor-opCall are arbitrarily complex, but there is no postblit, opAssign and dtor. P.S. I'm starting to hate the special nature of struct constructors: they can't have 0-arguments, now they disallow POD, what next? -- Dmitry Olshansky
Dec 29 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/29/2012 1:03 AM, Dmitry Olshansky wrote:
 I understand everything but constructors.
I think David brought that up as well, there seems good cause to relax that.
Dec 29 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/29/12 4:50 AM, Walter Bright wrote:
 On 12/29/2012 1:03 AM, Dmitry Olshansky wrote:
 I understand everything but constructors.
I think David brought that up as well, there seems good cause to relax that.
Great, thanks. Andrei
Dec 29 2012
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/29/12 4:03 AM, Dmitry Olshansky wrote:
 P.S. I'm starting to hate the special nature of struct constructors:
 they can't have 0-arguments, now they disallow POD, what next?
Yes, constructors should not influence the POD-ness of data; only postblits should. Andrei
Dec 29 2012
parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 29 December 2012 at 14:24:41 UTC, Andrei 
Alexandrescu wrote:
 On 12/29/12 4:03 AM, Dmitry Olshansky wrote:
 P.S. I'm starting to hate the special nature of struct 
 constructors:
 they can't have 0-arguments, now they disallow POD, what next?
Yes, constructors should not influence the POD-ness of data; only postblits should. Andrei
Default constructor may (even if they are not allowed, they may when disabled, which is allowed).
Jan 14 2013
prev sibling parent reply "Nicolas Sicard" <dransic gmail.com> writes:
On Saturday, 29 December 2012 at 01:53:15 UTC, David Nadlinger 
wrote:
  - There are also possible performance implications: Structs 
 that just wrap a single field in order to enrich it with type 
 information, such as Duration or a Quantity struct from a units 
 of measurement library, will likely benefit from being passed 
 in registers (if available), even if they will probably have 
 constructors. In fact, having such one-field structs behave 
 like a naked value might be vitally important to be able to 
 decorate a C API with e.g. units information (even if such code 
 would strictly speaking be architecture dependent).

 As far as I can see – and I'm merely guessing based on the 
 isPOD comment here – the only reason for not just applying the 
 C/C++ definition in the obvious way might be a quirk in the DMD 
 backend implementation?
I had started but never finished such a wrapping struct for units, and I gave it another try recently (https://github.com/biozic/siunits). Clearly, when using POD structs, the code of the function 'quality' in examples/rlc.d, executes way more rapidly (5x) than using non-POD structs. The only difference between POD and non-POD in my tests is the presence of non-default constructors, which is versioned out in the POD version. Code of the quality function with POD struct (compiled with -O -inline -release): --- push RBP mov RBP,RSP fld tbyte ptr 020h[RBP] fld tbyte ptr 010h[RBP] fld tbyte ptr [0FFFFE77Ch][RIP] fmulp ST(1),ST fld tbyte ptr 030h[RBP] fmulp ST(1),ST fdivp ST(1),ST pop RBP ret --- Same code with the non POD version (same compiler flags): --- push RBP mov RBP,RSP sub RSP,0B0h mov RSI,[00h][RIP] lea RDI,-040h[RBP] movsd movsd fld tbyte ptr [0FFFFE5C4h][RIP] fstp tbyte ptr -040h[RBP] mov word ptr -036h[RBP],0 mov dword ptr -034h[RBP],0 lea RSI,-040h[RBP] lea RDI,-050h[RBP] movsd movsd lea RSI,-050h[RBP] lea RDI,-060h[RBP] movsd movsd mov RSI,[00h][RIP] lea RDI,-030h[RBP] movsd movsd fld tbyte ptr 010h[RBP] fld tbyte ptr -060h[RBP] fmulp ST(1),ST fstp tbyte ptr -030h[RBP] mov word ptr -026h[RBP],0 mov dword ptr -024h[RBP],0 lea RSI,-030h[RBP] lea RDI,-070h[RBP] movsd movsd lea RSI,-070h[RBP] lea RDI,-080h[RBP] movsd movsd mov RSI,[00h][RIP] lea RDI,-020h[RBP] movsd movsd fld tbyte ptr 030h[RBP] fld tbyte ptr -080h[RBP] fmulp ST(1),ST fstp tbyte ptr -020h[RBP] mov word ptr -016h[RBP],0 mov dword ptr -014h[RBP],0 lea RSI,-020h[RBP] lea RDI,-090h[RBP] movsd movsd lea RSI,-090h[RBP] lea RDI,-0A0h[RBP] movsd movsd mov RSI,[00h][RIP] lea RDI,-010h[RBP] movsd movsd fld tbyte ptr 020h[RBP] fld tbyte ptr -0A0h[RBP] fdivp ST(1),ST fstp tbyte ptr -010h[RBP] mov word ptr -6[RBP],0 mov dword ptr -4[RBP],0 lea RSI,-010h[RBP] lea RDI,-0B0h[RBP] movsd movsd fld tbyte ptr -0B0h[RBP] mov RSP,RBP pop RBP ret --- I will use such a library in an environment that is not performance critical. But I hope that this will eventually be optimized. Thanks, Nicolas
Jan 14 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/14/2013 11:24 AM, Nicolas Sicard wrote:
 I had started but never finished such a wrapping struct for units, and I gave
it
 another try recently (https://github.com/biozic/siunits).

 Clearly, when using POD structs, the code of the function 'quality' in
 examples/rlc.d, executes way more rapidly (5x) than using non-POD structs. The
 only difference between POD and non-POD in my tests is the presence of
 non-default constructors, which is versioned out in the POD version.

 Code of the quality function with POD struct (compiled with -O -inline
-release):
Please make a bugzilla entry with this. Thanks!
Jan 14 2013
parent reply "Nicolas Sicard" <dransic gmail.com> writes:
On Monday, 14 January 2013 at 21:18:13 UTC, Walter Bright wrote:
 On 1/14/2013 11:24 AM, Nicolas Sicard wrote:
 I had started but never finished such a wrapping struct for 
 units, and I gave it
 another try recently (https://github.com/biozic/siunits).

 Clearly, when using POD structs, the code of the function 
 'quality' in
 examples/rlc.d, executes way more rapidly (5x) than using 
 non-POD structs. The
 only difference between POD and non-POD in my tests is the 
 presence of
 non-default constructors, which is versioned out in the POD 
 version.

 Code of the quality function with POD struct (compiled with -O 
 -inline -release):
Please make a bugzilla entry with this. Thanks!
Done: http://d.puremagic.com/issues/show_bug.cgi?id=9320 English is not my mother language, so I hope the summary is OK.
Jan 14 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/14/2013 2:10 PM, Nicolas Sicard wrote:
 English is not my mother language, so I hope the summary is OK.
Not to worry. I work with lots of ESL engineers, and your English is excellent.
Jan 14 2013
prev sibling parent "Chris" <wendlec tcd.ie> writes:
On Friday, 29 December 2006 at 13:41:20 UTC, Aleksey S. Skidan 
wrote:
 I just wonder if there's such a thing as POD type in D? I have 
 failed to find
 one. The extern(C) struct seems not to be the thing because it 
 is hardwired to
 the ABI.
POD = Prisoner of D?
Dec 28 2012