digitalmars.D - POD
- Aleksey S. Skidan (3/3) Dec 29 2006 I just wonder if there's such a thing as POD type in D? I have failed to...
- Hasan Aljudy (3/6) Dec 29 2006 Basic types and structs are POD (plain old data).
- Aleksey S. Skidan (11/17) Dec 29 2006 Great thanks, but I do know what POD is. But unfortunately D's structs a...
- Sean Kelly (3/24) Dec 29 2006 Sure, but the TypeInfo doesn't affect the size or layout of Foo.
- Frits van Bommel (32/45) Dec 29 2006 So? That doesn't have anything to do with POD-ness.
- Aleksey S. Skidan (5/5) Dec 29 2006 What it's all about is that I wanted to port my kernel from C++ into D. ...
- Frits van Bommel (11/16) Dec 29 2006 As I've said before, object.d isn't hard to port. The version for my
- Aleksey S. Skidan (4/20) Dec 29 2006 Great thanks I'll try it. Though IMHO it's not a convinient way (more C-...
- Walter Bright (4/7) Dec 28 2012 Another way, if you're feeling adventurous, is to write a program to rea...
- bearophile (6/9) Dec 19 2012 In LDC there are pragmas to disable specific
- Lars Ivar Igesund (6/9) Dec 29 2006 http://www.digitalmars.com/d/glossary.html#pod
- Red (16/16) Dec 19 2012 I am learning D and reading the Kindle spec. It says:
- Jonathan M Davis (8/11) Dec 19 2012 D structs really aren't necessarily PODs. They can be used as PODs, but ...
- Andrej Mitrovic (6/8) Dec 20 2012 Having regular functions doesn't change the state of PODs. Having a
- Maxim Fomin (6/18) Dec 20 2012 How presence of ctor/dtor/postblit affect the POD (in a sense of
- Andrej Mitrovic (4/6) Dec 20 2012 It doesn't, but the semantics are different. For example if you pass
- Walter Bright (8/14) Dec 28 2012 There's more than that. POD structs can exist solely in registers. Havin...
- Andrej Mitrovic (21/23) Dec 28 2012 I suggest we implement a compiler trait via __traits(isPOD, Type).
- Jacob Carlborg (4/7) Dec 29 2012 Do we need a new trait, can't this be done in pure D?
- Andrej Mitrovic (3/4) Dec 29 2012 It can, but it's simpler to do in the compiler as it already has an
- Walter Bright (7/12) Dec 29 2012 Yes for a new trait, for the reasons:
- Andrej Mitrovic (8/13) Dec 28 2012 These are good points and reminds us that we need to update the
- Walter Bright (3/5) Dec 28 2012 A "trivial" destructor is the implicit one that does nothing, i.e. it me...
- Walter Bright (42/45) Dec 28 2012 D's definition of POD:
- Andrej Mitrovic (6/49) Dec 28 2012 I think there's a bug here, it never checks for the presence of
- Walter Bright (8/13) Dec 28 2012 I don't think a dependency on opAssign is necessary. I think it's great ...
- David Nadlinger (70/71) Dec 28 2012 The definition of POD as used in the x86-64 System V ABI – and
- bearophile (69/75) Dec 28 2012 I have done a small experiment. This is C99 code:
- bearophile (5/7) Dec 28 2012 But it's not important, also because both versions have the same
- David Nadlinger (6/7) Dec 28 2012 Eww, AT&T syntax… ;)
- Walter Bright (20/23) Dec 28 2012 The idea with POD is not necessarily to be compatible with C++ POD, but ...
- Andrei Alexandrescu (6/9) Dec 28 2012 The idea was to leave C++ compilers to change the order of fields in
- Walter Bright (4/12) Dec 28 2012 I didn't know that, but it makes sense.
- David Nadlinger (15/30) Dec 28 2012 I didn't doubt that we can invent our own definition, just that
- Andrej Mitrovic (2/3) Dec 28 2012 This means it can be passed in registers (for anyone not aware of the te...
- Walter Bright (2/5) Dec 28 2012 More than that, it means they can live entirely in registers.
- Dmitry Olshansky (31/45) Dec 29 2012 I understand everything but constructors.
- Walter Bright (2/3) Dec 29 2012 I think David brought that up as well, there seems good cause to relax t...
- Andrei Alexandrescu (3/7) Dec 29 2012 Great, thanks.
- Andrei Alexandrescu (4/6) Dec 29 2012 Yes, constructors should not influence the POD-ness of data; only
- deadalnix (4/11) Jan 14 2013 Default constructor may (even if they are not allowed, they may
- Nicolas Sicard (106/119) Jan 14 2013 I had started but never finished such a wrapping struct for
- Walter Bright (2/9) Jan 14 2013 Please make a bugzilla entry with this. Thanks!
- Nicolas Sicard (3/20) Jan 14 2013 Done: http://d.puremagic.com/issues/show_bug.cgi?id=9320
- Walter Bright (2/3) Jan 14 2013 Not to worry. I work with lots of ESL engineers, and your English is exc...
- Chris (3/8) Dec 28 2012 POD = Prisoner of D?
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
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
== Quote from Hasan Aljudy (hasan.aljudy gmail.com)'s articleAleksey S. Skidan wrote: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.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
Aleksey S. Skidan wrote:== Quote from Hasan Aljudy (hasan.aljudy gmail.com)'s articleSure, but the TypeInfo doesn't affect the size or layout of Foo. SeanAleksey S. Skidan wrote: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.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
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: -------------------- 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
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
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
== Quote from Frits van Bommel (fvbommel REMwOVExCAPSs.nl)'s articleAleksey 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...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
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
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
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
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
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
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
On Thursday, 20 December 2012 at 10:57:08 UTC, Andrej Mitrovic wrote:On 12/20/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:How presence of ctor/dtor/postblit affect the POD (in a sense of changing structure size and alignment)?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.Agree, unless it is a non-static nested function struct which has hidden member.
Dec 20 2012
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
On 12/20/2012 4:12 AM, Andrej Mitrovic wrote:On 12/20/12, Maxim Fomin <maxim maxim-fomin.ru> 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. There needs to be an easy way to query a type to see if it is POD, and currently there isn't one.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 28 2012
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: and C++11 rules: 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
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
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
On 12/29/2012 4:38 AM, Jacob Carlborg wrote:On 2012-12-29 00:53, Andrej Mitrovic wrote: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.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?
Dec 29 2012
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
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
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
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
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
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
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 shrl $8, %ecx 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
(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
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
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
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
On 12/28/2012 7:37 PM, Andrei Alexandrescu wrote:On 12/28/12 10:12 PM, Walter Bright wrote: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.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.
Dec 28 2012
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
On 12/29/12, Walter Bright <newshound2 digitalmars.com> wrote:Remember, a POD type can be enregisteredThis means it can be passed in registers (for anyone not aware of the term).
Dec 28 2012
On 12/28/2012 8:06 PM, Andrej Mitrovic wrote:On 12/29/12, Walter Bright <newshound2 digitalmars.com> wrote:More than that, it means they can live entirely in registers.Remember, a POD type can be enregisteredThis means it can be passed in registers (for anyone not aware of the term).
Dec 28 2012
12/29/2012 7:12 AM, Walter Bright пишет:On 12/28/2012 5:53 PM, David Nadlinger wrote: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 OlshanskyAs 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.)"
Dec 29 2012
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
On 12/29/12 4:50 AM, Walter Bright wrote:On 12/29/2012 1:03 AM, Dmitry Olshansky wrote:Great, thanks. AndreiI understand everything but constructors.I think David brought that up as well, there seems good cause to relax that.
Dec 29 2012
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
On Saturday, 29 December 2012 at 14:24:41 UTC, Andrei Alexandrescu wrote:On 12/29/12 4:03 AM, Dmitry Olshansky wrote:Default constructor may (even if they are not allowed, they may when disabled, which is allowed).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
Jan 14 2013
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
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
On Monday, 14 January 2013 at 21:18:13 UTC, Walter Bright wrote:On 1/14/2013 11:24 AM, Nicolas Sicard wrote:Done: http://d.puremagic.com/issues/show_bug.cgi?id=9320 English is not my mother language, so I hope the summary is OK.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
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
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