October 24, 2002
"Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:ap0uki$119j$1@digitaldaemon.com...
> as an aside, have you though about changing the build from a 2 stage
> compile, link into a 3 stage build
> so it is compile,gather,link, where the gather stage, pulls in all the
> objects, and then with a full view of the final codebase can convert  some
> calls to non-virtual and perform optimisations on immutable items etc, in
a
> similar fashion to Java/CLR dynamic compilers.

Too many void*'s in C++ usually put an end to these kinds of global optimizations. I tried to do something similar once with function register usage across separate compilation items, it just worked out that so many things defeat the optimization that there wasn't a payoff.


October 25, 2002
Isn't this a good opportunity to fix the language so that it supports these kinds of optimizations, rather than hinder them?

Surely something can be done.

What things would you need to be true in order to cache locals in registers across function calls?  Make an attribute that supports the functionality, and make the compiler enforce it.  You don't have to use it, but if you do, you know the compiler will be able to generate better code.  Maybe "const" isn't the right choice of words, maybe "cachelocalaccess" would be better.

I still think that readonly is a desirable attribute even if it doesn't buy you any optimization potential.  It seems like if you don't have it, you leave dangerous holes in a component's armor that can be abused without so much as a typecast or compiler warning.  Or abused completely by accident.

Sean

"Walter" <walter@digitalmars.com> wrote in message news:ap9jaq$l0m$1@digitaldaemon.com...
>
> "Sean L. Palmer" <seanpalmer@directvinternet.com> wrote in message news:ap0mop$oka$1@digitaldaemon.com...
> > If you have this situation you should use volatile on things you want changes to show up immediately on.  Then the change will take effect on
> all
> > copies immediately, but everything else can use the old values.
> > If you think something might change, don't keep a const reference to it.
> > Just because something might break isn't a good enough reason not to do
> the
> > optimization.  Just needs enough language warnings and good support for
> > volatile too.
> > In many cases you use const when you don't expect something to change
> and/or
> > don't care if it changes.
>
> Unfortunately, I can't implement compiler optimizations that assume const means const, because it doesn't and too many programs break. This is one
of
> the reasons why const is useless as a type modifier.
>
>


October 29, 2002
"Sean L. Palmer" <seanpalmer@directvinternet.com> wrote in message news:apad69$1hgm$1@digitaldaemon.com...
> Isn't this a good opportunity to fix the language so that it supports
these
> kinds of optimizations, rather than hinder them?
>
> Surely something can be done.
>
> What things would you need to be true in order to cache locals in
registers
> across function calls?  Make an attribute that supports the functionality, and make the compiler enforce it.  You don't have to use it, but if you
do,
> you know the compiler will be able to generate better code.  Maybe "const" isn't the right choice of words, maybe "cachelocalaccess" would be better.
>
> I still think that readonly is a desirable attribute even if it doesn't
buy
> you any optimization potential.  It seems like if you don't have it, you leave dangerous holes in a component's armor that can be abused without so much as a typecast or compiler warning.  Or abused completely by accident.

Perhaps in a future version, but for now I think things are pretty full. Gotta do foreach, lambda functions, etc. <g>


February 12, 2004
In article <anrqs3$ic5$1@digitaldaemon.com>, Evan McClanahan says... ..
>> void fn(inout int a, inout int b)
>> {
>>   a = 3;
>>   printf("a = %d\n", a);
>>   printf("b = %d\n", b);
>>   printf("global_var = %d\n", global_var);
>> }
>> 
>> int main()
>> {
>>   global_var = 2;
>>   fn(global_var, global_var);
>>   return 0;
>> }
>> 
>> A "real" inout parameter passing would print:
>> a = 3
>> b = 2
>> global_var = 2
Actually, for pass-by-copy, the value of global_var is ambiguous. The value of either 2 or 3 is possible depending on whether we look at parameters from left-to-right or right-to-left.
>
>I don't think that I know what you mean.  Semantically, inout should be
>something that expects a value in, but can still change it in the
>function.  So I would expect inout to do what I imagine that it does:
>a = 3
>b = 3
>global_var = 3
>
>> So it is not "inout" but "ref"
>
>This is something of a pathological case, perhaps even an error, since both inouts end up pointing to the same place.  Yeah, inout might be a ref, but I imagine that it would be extremely hard for the compiler to do compile time checking that the inout parameters are all different for each function.  In fact, I can't really see a case where it would be proper or useful to do this, nor a way to pass it back in a reasonable manner in any case.  I think that the keyword is clear enough, and that if possible what you're doing in the above code should be classed as an error, or at least proscribed in the documentation.
>
>Evan

Let me just recap what the three alternatives are, their strengths and weakness, and then my suggested approach to solving this problem.

inout: This indicates that a parameter is used for both input and output. The problem seems to be the calling mechanism used. For instance, are we using pass-by-reference, pass-by-value-result (pass-by-copy), or pass-by-name.

ref: This indicates that the parameter is passed-by-reference (a pointer). The problem is that this method does not indicate that the parameter is used for input, output, or both.

shared: This particular name really does not tell you anything, other than the fact the variable can be modified by the called routine. This is perhaps the worst option because it leaves two things unanswered: (1) are we using pass-by-reference or pass-by-value-result; and, (2) is the parameter used for input, output, or both.

For those that don't know the difference between these calling methods, here is a quick definition of each, assuming the parameter we are passing is called ARG.

pass-by-value: The contents ARG are passed to the function.

pass-by-reference: The address of ARG is passed to the function, allowing modification by the called function.

pass-by-value-result: A temporary, T, is assigned the value of ARG. Next, we call the function using pass-by-reference using T in place of ARG. Lastly, when the function returns ARG is assigned the final value of T.

pass-by-name: This one is best explained by an example (in pseudo-C):
int index;
int array[2] = {2, 2};
void sub(int param /*assuming pass-by-name*/)
{
param = 3;
index++;
param = 5;
}
void main()
{
index = 0;
sub(aray[index]);
// array is now {3, 5}
}
The reason for this is because the body of sub gets transformed into:
array[index] = 3;
index++;
array[index] = 5;

Having said all of that, I believe the following rules present a much more
elegant solution to all of these problems:
1) All parameters shall be passed via either pass-by-value or pass-by-reference.
2) All parameters deemed as input shall be read-only.
3) The parameter passing mechanism used for input parameters shall be determined
by the compiler.
4) All output parameters shall be passed in using pass-by-reference.
5) Output parameters that are referenced prior to writing to them shall result
in an error message.
6) All inout parameters shall be passed in pass-by-reference.
7) All inout parameteres shall be initialized prior to the call of said
function. (Note, that this would be easy to verifiy for a local variable but can
be extremely hard if not impossible for globals).
8) All parameters shall be assumed to be an input parameter unless explicitly
stated otherwise.

In some of the examples, people want to pass in a large array without doing the
copy, and as such labeled them as inout. Note that this is no longer necessary
due to rules (2) and (3). Other problems such as those presented in function
'fn' are covered by rules (1) and (6).


- Eric
February 12, 2004
>2) is useless for optimization, since you can still change it

In C++, but not neccessarily in D!?!
There simply shouldn't be a const_cast<>() and you should restrict const
parameters not to alias with other non const parameters. Are there any other
problems? I don't know if "mutable" could cause problems, if D would get
something like this.


>4) in my experience, it has never found a bug for me

It has for me.


February 12, 2004
>Too many void*'s in C++ usually put an end to these kinds of global optimizations. I tried to do something similar once with function register usage across separate compilation items, it just worked out that so many things defeat the optimization that there wasn't a payoff.

Are there too many void *s in D?


February 12, 2004
>>The fact that in is not specified can only mean one thing
>
>No, it can mean whatever the programmer's previous language experience (or lack thereof) might suggest.

Isn't this true for any keyword? You have to learn the language, before using it.


February 12, 2004
>> I also prefer 'ref' to inout, also i would like to so 'in' dropped as
>nobody
>> is ever going to use it, it is implicit and hence redundant. Its a waste
>of
>> ascii.
>
>That's probably a good idea.


Either I'm stupid or this suggestion was part of my first (or second?) post
here. :confused:


February 12, 2004
>Probably too late to worry about this one, alot of people are probably attached to the in/out/inout scheme.  What D has now isn't really broken.

D still hasn't reached version 1.0, so this shouldn't be a problem.


February 12, 2004
>1b. Minimum-ascii thinking led to the horrible C syntax and butchered semantics that we have today.  Remember when you were first learning C?  I do.  It was awful.  Everything was so cryptic.


#							       include <stdio.h>
#						 define	    MAin   printf("%d\n"
#						 define	    mAIN	return 0
#						 define	    MaiN	 {static
#						 define	    mAlN	  ) {if(
#						 define	    MA1N	   char*
#						 define	    MAiN	    (!!(
#						 define	    mAiN	    atoi
#						 define	    mAln	    &1<<
#						 define	    MAlN	    !=3)
#						 define	    MAln	     )&&
#						 define	    MAIN	     int
#						 define	    maln	     --,
#						 define	    Maln	      <<
#						 define	    MaIn	      ++
#						 define	    MalN	      |=
#						 define	    MA1n	      ||
#						 define	    malN	      -1
#						 define	    maIN	       *
#						 define	    MaIN	       =
#						 define	    ma1N	       )
#						 define	    Ma1N	       (
#						 define	    Main	       ;
#						 define	    mA1n	       !
#						 define	    MAIn	       }
#						 define	    mA1N	       ,
MAIN	    mAIn
Ma1N	    MAIN
ma1N	    mA1N
mAiN	    Ma1N
MA1N ma1N mA1N maIn MaIN malN mA1N	    ma1n
mA1N			  maiN	    Main
MAIN      main Ma1N MAIN Ma1n mA1N MA1N maIN
mAin      mAlN		  Ma1n	    MAlN
mAIN      Main		  maIn	    MaIn
mA1N Ma1n maln mAin MaIn		  Main	    maIn
MaIN		   mAiN		  Ma1N	    Ma1N
Ma1n		   maln		  maIN	    mAin
MaIn		   ma1N		  ma1N	    Main
ma1n		   MaIN		  mAiN	    Ma1N
Ma1N		   Ma1n		  maln	    maIN
mAin		   MaIn		  ma1N	    ma1N
Main		   mAIn		  Ma1N	    mAIn
Ma1N		   mAIn		  Ma1N	    mAIn
Ma1N		   mAIn	     Ma1N mAIn	    Ma1N mAIn
Ma1N		  mAIn	     Ma1N mAIn	    Ma1N mAIn
Ma1N		mAIn	     Ma1N   mAIn  Ma1N	 mAIn
Ma1N mAIn Ma1N	     mAIn      Ma1N	 mAIn
Ma1N		     Ma1n		 ma1N
ma1N		     ma1N		 ma1N
ma1N ma1N ma1N ma1N		     ma1N		 ma1N
ma1N		 ma1N		     ma1N		 ma1N
ma1N		 ma1N		     Main		 MAin
mA1N maiN ma1N Main mAIN Main	     MAIn		 MAIN
mAIn	Ma1N		  MAIN	     mAin		 ma1N
MaiN	 MAIN		 main	       MaIN	       malN
Main	  main		MaIn		 Main	     mAIN
mA1N	   maiN	       MalN		   Ma1N	   MAiN
maIn	    mAln      main		       ma1N
MA1n	     Ma1N    MAiN		       ma1n
mAln	      main  ma1N		       MA1n
mAin		 MAln			       Ma1N
mA1n	      MAiN  ma1n		       mAln
main	      MAln  mAin		       ma1N
ma1N		 ma1N	   MAln Ma1N mA1n MAiN maIn
mAln		 main	   MAln
Ma1N		 MAiN	   ma1n
mAln	    main ma1N MA1n mAin MAln
Ma1N	    mA1n		MAiN
ma1n	    mAln		main
MAln	    mAin		ma1N
ma1N	    ma1N		ma1N
ma1N	    ma1N		Maln
main	    mA1N		MAiN
ma1n	    mAln		main
MAln	    mAin		ma1N
MA1n	    MAiN		maIn
mAln	     main	       MAln
Ma1N	       MAiN	     ma1n
mAln		 main ma1N MA1n
mAin		      MAln
Ma1N		      mA1n
MAiN		      ma1n
mAln		      main
MAln		      mAin
ma1N		      ma1N
ma1N		      ma1N
Main		      MAIn