From: Gabriel Dos Reis on 2 Dec 2006 17:13 Al <two(a)haik.us> writes: [...] | > Wouldn't nasal demons be an advantage, in practice? | | Well, I don't see how C++'s approach, i.e., anything can happen, | including expressly crashing the plane into the ground, or launching all | the nukes available intentionally, is _at all_ better than Java's | approach, i.e., one undefined numerical quantity with zero memory | corruption. I don't claim C++'s approach is better. But I do dispute that the Java alternative is better. I suspect we're here in a territory where there is no (unconditional) total order of behaviour. -- Gabriel Dos Reis gdr(a)integrable-solutions.net [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Andrei Alexandrescu (See Website For Email) on 2 Dec 2006 17:15 James Kanze wrote: > Andrei Alexandrescu (See Website For Email) wrote: >>I guess the set of "all hell breaks loose" is much larger, and includes, >>the set "there is one incorrect value". I am sitting here in amazement I >>have so much trouble getting this point across. > > > Certainly. The only point I'm trying to make (here---there seem > to be multiple issues being discussed in parallel) is that even > with Java's "defined behavior", all hell can break loose. That > both are really "undefined behavior". > > Except that we're not really discussing the undefined behavior I > find in Java. I agree that requiring error checking is a good > thing. And that C++ has too much undefined behavior, especially > in a lot of cases where there's absolutely no need for it. > Somehow, the argument has gotten away from my statement that all > languages have some forms of undefined behavior. And I disagree with that statement - as simple as that. There are definitely languages (Haskell, ML) that do not have undefined behavior. So you'd need at least to qualify your statement with "all non-academic languages have some forms of undefined behavior". Even after that qualification, I still disagree with you, subject on how you define "undefined behavior". If you define "undefined behavior" as in C++, then I flat out disagree with you. If you defined "undefined behavior = produces undefined numbers", then I'd agree. The fact that we're in a C++ forum suggests that "undefined behavior" carries the C++ conotation of the phrase, which is "there is no guarantee about this program henceforth". So I want to clear that out. To summarize so far: (1) I find your statement "all languages have some forms of undefined behavior" wrong because there are languages, be they academic or of limited market penetration, that do not have undefined behavior; (2) Even after we restrict the statement to industrial languages, the statement is still wrong because it uses "undefined behavior" with its implicit C++ meaning. > On the other hand, it's impossible to eliminate it entirely; > some of it comes directly from the hardware we run on, and > eliminating other cases (e.g. some of the threading issues) > really does impose unacceptably high run-time costs. IMHO the whole non-deterministic hardware branch of discussion is a big smelly red herring pulled on the trail. This is not a hardware forum. We discuss the whole issue within the confines of a hardware model, and artificially taking the discussion to metaphysical levels would only lead to purpose-of-life kind of questions. > Try doing any multithreaded programming without proper > synchronization, and you'll get unpredictable results. The > language standard doesn't specify what happens globally, even if > it tries to specify most individual accesses. And if what > happens isn't defined, how can you say that it isn't > "undefined". I Java, I'll get wrong numbers but never violated objects. The program remains well-defined, only the numbers subject to races have undefined content. Andrei -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Walter Bright on 3 Dec 2006 06:18 Gabriel Dos Reis wrote: > Walter Bright <walter(a)digitalmars-nospamm.com> writes: > > | Gabriel Dos Reis wrote: > | > Fortunately, not all compilers out there made the decision to actively > | > unsupport abstractions like the Digital Mars compiler. > | > | Name one that returns std::complex values in a register pair. > > I did in the part that was consciously left out from your reply. > > GCC/g++. You didn't mention GCC/g++ or x86-64. You mentioned the PowerPC and the Itanium. It's hard to elide something that wasn't there. Furthermore, the ABI quotes you gave in one place say the size has to be 8 bytes or less (won't work for complex types), and another quote only talks about single values, not multiple values (in register pairs). > Given > > #include <complex> > > std::complex<double> > add(std::complex<double> x, std::complex<double> y) > { > return x + y; > } > > It produces, for a target that identifies itself as x86_64-suse-linux, > > _Z3addSt7complexIdES0_: > .LFB1756: > addsd %xmm3, %xmm1 > addsd %xmm2, %xmm0 > ret > Good for g++ on the X86_64. g++ for the x86 does not do this (I checked it), although there are floating point registers available. The asm output of g++ is cut and pasted from actual g++ output. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Gabriel Dos Reis on 3 Dec 2006 06:20 "Jeffrey Yasskin" <jyasskin(a)gmail.com> writes: | On Nov 30, 7:27 am, Gabriel Dos Reis <g...(a)integrable-solutions.net> | wrote: | > The Itanium Software Conventions and Runtime Architecture Guide | > specifies (page 8-13) that certain aggregates are returned in | > registers. That is lift to C++ UDT if they don't have non-trivial | > *copy-constructor* or *destructor*. See the "common C++ ABI" | > specification | > | > http://www.codesourcery.com/cxx-abi/abi.html#calls | > | > In general, C++ return values are handled just like C return | > values. This includes class type results returned in | > registers. However, if the return value type has a non-trivial copy | > constructor or destructor, the caller allocates space for a | > temporary, and passes a pointer to the temporary as an implicit first | > parameter preceding both the this parameter and user parameters. The | > callee constructs the return value into this temporary. | | Since std::complex has a non-trivial copy constructor Not with any version of GCC/g++ I've been using for more than half a decade now. | (well, actually it can be trivial; Not just it can; it *is* trivial. I carefully implemented that library component that way. | libstdc++ in gcc 4.0.0 does it...), it can't be returned in | registers on the Itanium. What if you tried and it did, would you call it a miracle? :-) I already posted this example, but I'll produce it again: #include <complex> std::complex<double> add(std::complex<double> x, std::complex<double> y) { return x + y; } For the target x86_64-suse-linux, GCC/g++ generates: _Z3addSt7complexIdES0_: .LFB1756: addsd %xmm3, %xmm1 addsd %xmm2, %xmm0 ret | Are there any ABIs that allow it? Yes, but apparently you don't want to believe. | I know very little about ABI design, but I'd guess that it's very | tricky to specify that a compiler must implement a particular level of | optimizations on an interface boundary. The ABI specification in binding. Therefore, it does not become an optimization anymore -- by definition, an optimization does not change the observable behaviour. If you have an ABI that says, the compiler must return in register in particular circumstances, then the compiler has no choice, it must do it. Otherwise it miscompiles programs. If you have an ABI that says the compiler must return in memory, the compiler must do it that way. | Walter's opportunity is to | define a language feature that would let a library writer help the | compiler pass and return UDTs in registers even when the copy | constructor is non-trivial, and do it uniformly enough to specify in | the ABI. I'm disputing very specific claims, not vapor language features. -- Gabriel Dos Reis gdr(a)integrable-solutions.net [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Gabriel Dos Reis on 3 Dec 2006 06:21
Walter Bright <walter(a)digitalmars-nospamm.com> writes: [...] | For example (I think we can agree that Foo doesn't get any more trivial!): Sure! | ------------- C++ ------------------ | struct Foo { int x; }; | | Foo bar(int i) | { | Foo f; | f.x = i; | return f; | } | ------------- g++ ------------------ | _Z3bari: | pushl %ebp | movl %esp, %ebp | movl 8(%ebp), %edx | movl 12(%ebp), %eax | movl %eax, (%edx) | movl %edx, %eax | leave | ret $4 | ----------- DMC++ ------------------ | ?bar@@YA?AUFoo@@H@Z: | mov EAX,4[ESP] | ret | ------------------------------------ | g++ is returning f on the stack, DMC++ in register EAX. I don't know which g++ you're using as g++ and which platform you're compiling for, but an old version of g++ (4.1.0) I have on a machine that identifies itself as x86_64-suse-linux compiles your function bar to: _Z3bari: .LFB2: movl %edi, %eax ret -- Gabriel Dos Reis gdr(a)integrable-solutions.net [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |