RE: Re: RE: Re: WinAVR continuation

Go To Last Post
36 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And please, remember about Bug c++/43745 "“ it is really annoying to have vtables in SRAM:
http://gcc.gnu.org/bugzilla/show...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
it is really annoying to have vtables in SRAM

Unfortunately, this one is anything else but easy to fix.
Others already looked into it, and eventually gave up. :(

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
it is really annoying to have vtables in SRAM

First step would be to do a proper bug report with code that compiles instead of some phantasy code ;-)

The put-in-flash-part should be doable, but what is not doable at the moment is to access that stuff. The backend will just get a pointer, so there is no way to know how the access should be made and how address generation should be done. IMO this is nothing you will see in the near future.

Linearizing address space is no option.

Anyway, using vtables on a small µC is kind of overkill.

dl8dtl wrote:
> where GCC is with generic multi-memory space support?

Ask Georg-Johann.

Up to now it's nowhere; at least as far as I know. There was some effort by Atmel, dunno how far they got.

All I have is the result from an afternoon of hacking out curiosity that showed that it is not hard to do.

But as always, the hard things will be the details.

Another drawback is that tere is absolutely no test code; all I tried were accesses <= 16 bits. I have no idea what struct foo = struct bar will do...

But as Eric said, priority is to get rid of bugs.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
Anyway, using vtables on a small µC is kind of overkill.

I have no particular argument with that, though I can think of places ( menu structures, etc. ) where C can come pretty close to implementing something like vtables anyway. The important point, though, is that it is an integral feature of the language - it needs to work and work reasonably. At the moment it is functional, but it does have distinct ( and visible ) drawbacks. Perhaps the programmers that run into the issues should choose another approach, but it is never good to see things that you know could be "right" but aren't. A place I see the same issue in the avr-libc support is ( at least last I checked ) 64-bit arithmetic. People who attempt to use it are likely to get a large ( in many ways ), and quite unpleasant surprise.

All that having been said, I agree entirely that the first ( and perhaps only ) priority for an initial new WinAVR version, needs to be bug-fixes; documentation might come a near second, however, where there are specific requests for clarification ( I've personally found the avr-libc documentation sufficient ).

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
TFrancuz wrote:
it is really annoying to have vtables in SRAM

First step would be to do a proper bug report with code that compiles instead of some phantasy code ;-)

The put-in-flash-part should be doable, but what is not doable at the moment is to access that stuff. The backend will just get a pointer, so there is no way to know how the access should be made and how address generation should be done. IMO this is nothing you will see in the near future.

I don't see the problem.
I would see a problem if only some vtables were in flash.
With all vtables in flash,
it's just a matter of using LPM instead of LDS.
That LPM, ICALL and IJMP all use the
Z pointer does make things clumsier,
but I don't see that that would make
it much harder for an automaton.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To me vtable looks like look up table – in both cases we have a list o pointers. But look up tables are placed by avr-gcc entirely in FLASH, whereas vtables are copied into SRAM. I can’t see why changing it is so difficult – we already have vtables in FLASH, because start up code only copies it into SRAM, which should be easy do change. Second part is the code, which actually realizes a jump to address pointed by vtable entry – all which must be done, is to change the code, so it will read vtable from FLASH instead of SRAM. Because pointers to virtual methods should always be pointing to FLASH, there is no problem with different address spaces and so on. We can just treat a pointer to virtual method always as a pointer to FLASH.
BTW, using virtual methods is not an overkill, even on AVR8. Jump to vmethod is only a bit longer than to a regular method. It is an overkill, because of SRAM usage by classes with virtual methods. In most of my C++ apps on AVR, more than 30% of SRAM is wasted by vtables. It is an overkill.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
"vtables in flash are easy to implement in g++."
It does not matter if it appears to be easy from a perspective outside GCC. The only thing that matters is how complicated it is from inside GCC.

As this thread started as announcement for WinAVR continuation, it won't come with such an extension, anyway.

The only low-hanging optimization fruit that is available ouside current development branch is LTO. I don't know if Eric plans to build the release with LTO enabled and what version of binutils he prefers.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
TFrancuz wrote:
"vtables in flash are easy to implement in g++."
It does not matter if it appears to be easy from a perspective outside GCC. The only thing that matters is how complicated it is from inside GCC.

As this thread started as announcement for WinAVR continuation, it won't come with such an extension, anyway.

I understand that, but by the way I would like to know, why putting vtables in FLASH is so difficult task, and you seem to be a person who knows the answer. That’s why I asked.
And BTW, please don’t cite somebody’s else words as mine.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
SprinterSB wrote:
...
The put-in-flash-part should be doable, but what is not doable at the moment is to access that stuff. The backend will just get a pointer, so there is no way to know how the access should be made and how address generation should be done. IMO this is nothing you will see in the near future.
I don't see the problem.
I would see a problem if only some vtables were in flash.
With all vtables in flash,
it's just a matter of using LPM instead of LDS.
That LPM, ICALL and IJMP all use the
Z pointer does make things clumsier,
but I don't see that that would make
it much harder for an automaton.

SprinterSB wrote:
Comments like "it's no problem, just replace LDS by LPM" are in crass discrepancy to an actual implementation.
Note that my comment was in response to the claim that the backend couldn't know what to do with a pointer.
Perhaps I should have been less diplomatic and just written "HUH?".

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
SprinterSB wrote:
Comments like "it's no problem, just replace LDS by LPM" are in crass discrepancy to an actual implementation.
Note that my comment was in response to the claim that the backend couldn't know what to do with a pointer.

The gcc backend isn't a linear piece of code, i.e. it don't get the high-level program representation with the instruction to produce low-level or assembly out of it. Instead, a gcc backend is a collection of hundreds of macros, hook functions and patterns that are called in target independent code then and when to query for target dependent information or perform target dependent action.

One such question is "is this a valid address?" For "register + register" you would return "no" and for "register plus constant" you would return "yes". So the backend knows about addresses, but there are not different kinds of addresses. This is because for the hardware it does not matter if you read a pointer from memory or an integer or the component of some structure or a volatile. Similary the backend is told to emit code that reads a location like "here is a register that contains an address. Get me its content to that register". There is no high-level information there.

Even if the backend could determine that an access is to flash (e.g. because it sees a specific symbol or attribute) it would not help to treat it as flash-access because that would not be consistent throughout gcc. gcc never had the need to destinguish pointers on that level, so the information is simply not handled or passed around in all backend places or optimizer passes. Any such attempt would sooner or later produce wrong code.

The only vehicle that is capable of doing that are named address spaces. That actually will add the question "is this a valid foo-space address?" or the task "here is a register that contains a foo-space address. Get me its content to that register".

TFrancuz wrote:
SprinterSB wrote:
TFrancuz wrote:
"vtables in flash are easy to implement in g++."
And BTW, please don’t cite somebody’s else words as mine.
Was just paraphrasing :-)

TFrancuz wrote:
SprinterSB wrote:
As this thread started as announcement for WinAVR continuation, it won't come with such an extension, anyway.
I understand that, but by the way I would like to know, why putting vtables in FLASH is so difficult task, and you seem to be a person who knows the answer. That’s why I asked.
Ok. Let me give an overview what would have to be done in gcc:
  • Put the vtable in a specific section like, e.g. .progmem.data. If the backend cannot tell if a specific object is a vtable or never sees vtables, then
  • Add a hook in the C++ frontend that queries for the section or any other information needed. Treat that information appropriately.
  • Implement a named address space in avr backend. Currently they are supported for C and the generation of an address in that space is triggered by a qualifier-like keyword like __pgm.
  • Building of a named address is not triggered by sourcecode here. Thus, the C++ frontend needs more extension: Add a hook that queries for the address space for a vtable. Treat that information appropriately.
  • Do all the work needed around that spots: Document the new hooks in the internals, write test cases, test for all languages, platforms and machines where this might have negative impact, etc.
If you are lucky, that's it. If not, you will see the compiler crash or generate wrong code. The cause might be that now named addresses occur in places they didn't occur before the extension outlined above, so the real hard parts might be "Treat that information appropriately".

avrfreaks does not support Opera. Profile inactive.

Last Edited: Sun. May 29, 2011 - 09:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
Ok. Let me give an overview what would have to be done in gcc:
  • Put the vtable in a specific section like, e.g. .progmem.data. If the backend cannot tell if a specific object is a vtable or never sees vtables, then
  • Add a hook in the C++ frontend that queries for the section or any other information needed. Treat that information appropriately.
  • Implement a named address space in avr backend. Currently they are supported for C and the generation of an address in that space is triggered by a qualifier-like keyword like __pgm.
  • Building of a named address is not triggered by sourcecode here. Thus, the C++ frontend needs more extension: Add a hook that queries for the address space for a vtable. Treat that information appropriately.
  • Do all the work needed around that spots: Document the new hooks in the internals, write test cases, test for all languages, platforms and machines where this might have negative impact, etc.
If you are lucky, that's it. If not, you will see the compiler crash or generate wrong code. The cause might be that now named addresses occur in places they didn't occur before the extension outlined above, so the real hard parts might be "Treat that information appropriately".

Forgive me my naive way of thinking. You proposed a proper and complicated solution. So let’s think from the opposite side. We have a working function (pattern) which is responsible for calling virtual methods. Our “function” reads the pointer from SRAM. Can’t we just change it, so it will read a pointer from FLASH instead? I think that a “function” which is a pattern for generating calls of virtual methods is a separate code in gcc? Vtables are in a well defined place in FLASH, in that case we only need to modify startup scripts (linker scripts) not to generate code which will copy vtables from FLASH into SRAM. I know that this solution will not be accepted by gcc developers, but still it can be included as a patch in WinAVR, and it should be relatively easy to implement. I tried to look into gcc internals, but it’s a lot of macros, not well documented. At least I can’t find any good gcc internals documentation. BTW, can you recommend one?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am also not familiar with the gcc internals, but I think the import point you miss is that gcc is a compiler for several platforms/architectures/languages and that it works therefore with an intermediate code.

TFrancuz wrote:
We have a working function (pattern) which is responsible for calling virtual methods. Our “function” reads the pointer from SRAM.
No. That "function" does not read anything from anywhere. It only generates some intermediate code saying something like "resolve function pointer from a table with this symbol as base address and that symbol as index". Then this intermediate code traverses additional steps (like optimization), and then many steps later the resulting intermediate code is translated into AVR code. And the problem is now (if I understand Georg-Johann right) to hook additional information to the "symbol with the base address" so it gets passed through all that steps.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Probably you are right. But in that case it should be even simpler to modify. As I said, avr-gcc can perfectly work with look up tables. For example, if you have a big switch/case block, it can be implemented by gcc as a look up table. So, the intermediate code must contain specific instructions to take a pointer – “resolve function pointer from a table with this symbol as base address and that symbol as index", and the table is in FLASH. Exactly the same mechanism should be implemented in case of vtables and virtual method call.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:
I am also not familiar with the gcc internals, but I think the import point you miss is that gcc is a compiler for several platforms/architectures/languages and that it works therefore with an intermediate code.
I had forgotten that.
https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=809816&highlight=wonder#809816

So the problem is to get the section information
into the AVR backend in a manner that doesn't require
too much repair work on the other backends.
How close would flagging vtables with the section attribute come to doing the trick?

For me, this will probably remain an intellectual exercise.
I don't anticipate using vtables on an AVR anytime soon.
That said, having them in flash might lower the threshold

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:
TFrancuz wrote:
We have a working function (pattern) which is responsible for calling virtual methods. Our “function” reads the pointer from SRAM.
No. That "function" does not read anything from anywhere. It only generates some intermediate code saying something like "resolve function pointer from a table with this symbol as base address and that symbol as index". Then this intermediate code traverses additional steps (like optimization), and then many steps later the resulting intermediate code is translated into AVR code. And the problem is now (if I understand Georg-Johann right) to hook additional information to the "symbol with the base address" so it gets passed through all that steps.
Yes, that's the crucial point. The frontend will emit something like "add a value to a pointer" then "dereference the pointer" and "call a function at that location".
sternst wrote:
[...] gcc is a compiler for several platforms/architectures/languages and that it works therefore with an intermediate code.
GCC actually works on two intermediate representations. FYI:
  • The first are "tree"s; they are what you would expect: A low-level representation of the program's atoms.

    To get an idea of how it looks like and how it gets transformed, add "-fdump-tree-all" to gcc's command line. That will dump some C-like files. Increasing number in the t-dump represents increasing pass order.

  • The second representation is RTL (register transfer language). A piece of RTL called insn is an algebraic formulation of an assembler equivalent. A gcc backend operates on this RTL representation and is partly written therein. To see the lisp-like r-dumps of RTL, add "-fdump-rtl-all" or "-da" to the command line. The gcc passes that operate on RTL are still written target independent and not contained in a backend.

    To see the correspondance between RTL and assembler, see the s-file dumped with "-save-temps -dP".

skeeve wrote:
So the problem is to get the section information into the AVR backend [...] How close would flagging vtables with the section attribute come to doing the trick?
That's the part that put's the table in flash. But an attribute is not strong enough for the access (to survive all intermediate crunching). What is needed is a qualifier.
wek wrote:
SprinterSB wrote:
To accomplish that, write the function in assembler and add it to libgcc or avr-libc.
Any list?

? You like to know what mainling list?

For patches agains avr-libc avr-libc-dev looks good, maybe also avr-gcc-list. See [1] for the lists.

The GCC lists are listed in [2]. Patches against GCC are gcc-patches. You find some policies about contributing in [3].

If you intend to do the patches against GCC, the files you have to touch are
./gcc/config/avr/libgcc.S
./gcc/config/avr/t-avr
and changelogs will be relative to
./gcc/ChangeLog

You will find it easier to integrate into avr-libc than to libgcc, and likely the result will reach the audience sooner because arv-libc has shorter release cycles.

[1] http://lists.gnu.org/archive/html/
[2] http://gcc.gnu.org/lists.html
[3] http://gcc.gnu.org/contribute.html

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, vtables again :)
I’ve been looking into gcc internals described in online docs, and found something interesting.
We already have instruction patterns, like tablejump, which take an address from FLASH and jumps. Basically it does what we need to implement vtables in FLASH. So the only problem seems to be how to change g++ to produce tablejump insn when accessing virtual method. Or am I wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

[Ignore: Posting just to get this thread into "My posts" lists]

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

tablejump pattern is the wrong place to look. It's used for switch/case and comletely different stuff. It might appear similar but that does not help anything. Moreover, as written above, the c++ FE does not emit instruction patterns.

You may want to have a look at
./gcc/cp/decl.c:cxx_init_decl_processing
./gcc/cp/class.c:build_vtable
and how they define/layout/use vtable_entry_type, vtbl_type_node, vtable_type et al.

For a serious discussion gcc@gcc.gnu.org is the right mailing list, so sign up and f'up there.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks. I know about mailing list, but I’m sorry to say that, but to me it seems that gcc developers are living in their own word, and it’s a problem to communicate with them. Once I tried, I’ve got a response like – wrong list, got to gcc-help, they didn’t even notice that AVR is Harvard architecture, so I’ve got a messy response.
I will try with files you mention, I hope that I can count on your help in this topic?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
I will try with files you mention, I hope that I can count on your help in this topic?
I am not familiar with the C++ FE. Anyway, without named address space support in avr BE you dont't have a way to express what you intend to express.

With a working named address space support in avr BE you can return to gcc and ask what bits are missing to close the gap between backend and frontend.

Named addresses are here:
http://gcc.gnu.org/onlinedocs/gc...

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I’m sorry to say that, but to me it seems that gcc developers are living in their own word, and it’s a problem to communicate with them.

I'd say that on the list there is more focus on the internals of the compiler, the run-time lib and so on. There is less traffic on "How do I do this with an AVR?"-type questions. It's just different cultures. And when you try to talk on e.g. the avr-gcc list you should have done your reading up.

Here on AVRfreaks the culture is less rough in this respect. (Not that we do not bash the self-inflicted-clueless or the people trying to get school work done with no effort on their on...)

By and large, the people on the avr-gcc/avr-libc/AVRDude lists are just as nice, helpful and polite as here on freaks. Just somewhat different cultures. It always helps to read through old threads or go through a few digests in a mailing-list-archive to get the feel for the way to move in a certain social environment. Remarkably like Real Life [tm], if you ask me...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does GCC really copy the vtable to RAM for every instance of a virtual class? Or does it just create a single copy of the vtable in RAM?

Josh

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Josh! I have not checked, but I would be surprised (to say the least) if it created a copy for every instance. Why would it? I've heard of no C++ compiler that creates v-tables per instance.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting, I kind of assumed that, but some of the posts made it sound like a majority of their RAM was being taken by vtable copies... I'm not sure this is a huge deal for a microcontroller (at least not for my project), I have maybe 4 distinct classes that have 1, or maybe 2, virtual methods; all my other classes use static dispatch.

If all the work was done to add this GCC feature, would it save me all of 16 bytes of RAM (4 16-bit vtable entries for 4 classes)? I assume there is also a 16-bit vtable pointer that is copied into RAM for each instance, I would think this could add up much more quickly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I assume there is also a 16-bit vtable pointer that is copied into RAM for each instance

Yes, it is a part of the "object structure"(i.e. what the this-pointer is pointing to in a called (non-static) member function).

Another way of saying this is that a virtual function call is actually equivalent to something like this (for a call from a member function to a virtual member function):

this->vtable->func(this, parameter1, parameter2 ...)

Quote:

If all the work was done to add this GCC feature, would it save me all of 16 bytes of RAM (4 16-bit vtable entries for 4 classes)?

Yup.

Quote:

I assume there is also a 16-bit vtable pointer that is copied into RAM for each instance, I would think this could add up much more quickly.

Yup.

Alo: Apart from the RAM consumption, this might be an issue with code size / execution time (if RAM access is more compact or faster than flash access).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:

Another way of saying this is that a virtual function call is actually equivalent to something like this (for a call from a member function to a virtual member function):

this->vtable->func(this, parameter1, parameter2 ...)

Is the vtable pointer actually variable between instances? Could it technically be implemented as?

MyClass::vtable->func(this, param1, param2 ...)

I could see going to the work to make the vtable pointer stay in flash being worth the work, more than the vtable iteslf...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For the technical aspects you will have to dive into the C++ frontend: http://gcc.gnu.org/viewcvs/trunk...

(Intrinsic) named address spaces are only mentioned as a language extension to C++, see ISO/IEC DTR 18037, Annex F.2, which is not imlemented in GCC.

PR43745 does not imply to expose named address spaces to the user, yet "bits" of named address suppport in GCC's C++ front end are missing, of course.

As PR43745 is 1 1/2 years old now and no one even managed to supply a small example that shows the problem, I'd guess that PR is bug-rot and can be closed?

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Is the vtable pointer actually variable between instances?

Yes, AFAIK it must be or the polymorphism would not work. The point is that when you have a pointer to a superclass it is not known what subclass the object (pointed to) actually is. Thus each object has to be able to inform about where the applicable vtable is.

Sketchy example:

class Super
{
public:
   virtual void foo() = 0;
};

class Sub1
{
public:
   virtual void foo() {...}
};

class Sub2
{
public:
   virtual void foo() {...}
};

void main(void)
{
   Super * objects[10];
   for (int i = 0; i < 10; i++)
   {
      if (rand() > 0.5)
      {
         objects[i] = new Sub1();
      }
      else
      {
         objects[i] = new Sub2();
      }
   }

   for (int i = 0; i < 10; i++)
   {
      objects[i]->foo();
   }
}

There is no way to tell at compile time what objects will be created. Thus the compiler must generate code that at run-time determines what foo() is called. Thus every object needs to have information making this possible. Although the C++ standard says nothing specific about how this is to be implemented, but leaves it open to the implementers, the only variant I've seen/heard of is for every object to have a pointer to it's vtable. (With multiple inheritance it might be a little more involved, but the principle about every object knowing still holds.

This is also, at least conceptually, closely related to RTTI.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

guys,
after the recent activity on another thread https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=69747&postdays=0&postorder=asc&start=60&sid=16ea510d43297f5a67df48fc92380520 I came across this one.

was there ever a conclusion as to whether this enhancement could be scheduled?

my experimentation with some reasonably simple example (1 x virtual function in base class) shows a cost of 6 bytes per class type plus 2 bytes per class instance.

so.... in a despatcher example for an atmega16 that i have been looking at I have 26 instances and what would be 16 different class types give 16x6 + 26x2 = 148 (of 1024) bytes. That is a big cost.

regards
Greg

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg,

The best place to start that research would be to find out if you really need polymorphism. Are you actually calling all of those virtual member functions through a pointer to a base class instance ? Throw in a few examples of how you need it.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chauncey!

Since he mentions a "despatcher" I would speculate that it is "the Run() function" that is virtual.

On e of the school book examples of polymorphism in action.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sure. Schoolbooks are useful in the appropriate context - the school - but in reality too much abstraction for a simple problem comes at a cost at more than one level.

I think I read somewhere the other day that some Atmel guys had recently implemented the bubble sort algorithm in assembly. That's a joke if there ever was one.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Chauncey!

Since he mentions a "despatcher" I would speculate that it is "the Run() function" that is virtual.

One of the school book examples of polymorphism in action.


This is correct.

I have been converting a small project to cpp mainly as a learning exercise.

I have a small executive where application processes are implemented as state machines in c functions. the despatcher calls the applications processes via an array of pointers to functions where the argument to the function is an event for each application process. this is very straightforward in c.

I have converted all my queues, timers and other support functions to classes. The design is cleaner and the memory usage is reduced!

I am having a look at what would be involved in converting some/all of the application processes to be classes. Although there are some advantages in the application processes the despatcher seems to consume heaps of ram for vtables.

the concept is...

class base
{
    virtual void run(event);
}

class procN: public base
{
    void run(event)
    {
        // do the stuff for user process N
    }
}

base procTable[] = {pointers to proc1.. procN}

events are delivered by indexing procTable[] with the pid and calling run()

If there is a simpler method I am interested to know it.

The approach outlined above is way expensive with RAM usage.

regards
Greg

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I have been converting a small project to cpp mainly as a learning exercise.

So is the whole vtables in flash thing brouhaha? If it's not something that actually affects working, concrete examples of real application code on AVRs why does anyone care? And when those folks turn up saying "C++, bloat, "hidden RAM", etc" ask them for their concrete example of where it's happening too.

I'm sure there are areas of the compiler with a stronger justification for research/engineering than some navel fluff examination if that's what this is?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Sure. Schoolbooks are useful in the appropriate context - the school - but in reality too much abstraction for a simple problem comes at a cost at more than one level.

OK, let me rephrase: A scheduler is for me an excellent example of where C++ virtual functions really helps make for nice, redable, optimized-for-maintenance code.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gregd99 wrote:
the concept is...

class base
{
    virtual void run(event);
}

class procN: public base
{
    void run(event)
    {
        // do the stuff for user process N
    }
}

If there is a simpler method I am interested to know it.

The approach outlined above is way expensive with RAM usage.


Whether a less expensive approach is simpler or not depends on how big N is.

But even for non-small N you still have to create and add each process to your array - and apparently keep a mapping between each process and its place in the array.

gregd99 wrote:

base procTable[] = {pointers to proc1.. procN}

events are delivered by indexing procTable[] with the pid and calling run()


How are these "events" created ? How is the "pid" for any given event determined ?

It would be easier to suggest a simpler solution if you posted more code.

JohanEkdahl wrote:
OK, let me rephrase: A scheduler is for me an excellent example of where C++ virtual functions really helps make for nice, redable, optimized-for-maintenance code.

To me, it depends on how complicated the alternative would be. Adding abstractions doesn't necessarily make the code easier to read or maintain.

I also look at whether or not I can afford the cost of making the code "easier".

If the code actually is easier - to me, that means simpler - why would that come at a cost ? Code that actually is simpler tend to generate smaller binaries.

Sid

Life... is a state of mind