I have been developing embedded software for the Microblaze processor for more than a year using C++. My designs were not so complex, so I wasn't using the powerful, object-oriented features of the language.
For a while, I have been trying to enhance the structure of my designs. For this purpose, I try to widely use the sophisticated features of C++ such as inheritance, polymorphism, etc. As a newbie, I believe that using inheritance solely doesn't affect the code size. Only the polymorphism has some side effects like adding virtual table pointers, run-time-type-informations, etc. My problem started with adding a pure virtual member function to a base class.
To provide a runnable example, I will try to mimic the situation that I face against.
The code below compiles and produces 13292 bytes of code. There is no way that this code can have such an amount of instructions. But, I believe that there are some parts from the generated BSP that are mandatory to include when producing an elf file.
class Base{
public:
Base() = default;
~Base() = default;
virtual void func() {}
int m_int;
};
class Derived : public Base{
public:
Derived() = default;
~Derived() = default;
void func() final {}
int m_int2;
};
int main()
{
Derived d;
while(1);
}
13KB is not that much when you think that you have nearly 128KB of usable RAM. Actually, I didn't even notice the size of the produced code until the problem with the pure virtual functions emerges. The second code, below, has the same structure except for the func()
is now a pure virtual function. Building this code gives us a code size which more than the available*(128KB)* RAM size. So, I modified the linker file to add some fake RAM just to be able to compile the code. After a successful compilation, the size of the produced code is nearly 157KB!
class Base{
public:
Base() = default;
~Base() = default;
virtual void func() = 0;
int m_int;
};
class Derived : public Base{
public:
Derived() = default;
~Derived() = default;
void func() final {}
int m_int2;
};
int main()
{
Derived d;
while(1);
}
I didn't change any preferences of the compiler, all arguments are in their default states. There are no additional libraries other than the auto-generated ones. What do you think that the problem could be?
Some Additional Notes
- I tried the codes on two different IDEs. Vivado SDK 2017.2 and Vitis 2019.2
- The same problem also goes for the dynamic allocation calls(operator new and delete). Replacing them with C-Style malloc and free solves the problem.
- Building the codes in the release mode solves the problem also. In release mode, the produced code is 1900 bytes whether I use the pure virtual function or not.
I can provide additional information if needed, thanks
I asked the same question on Xilinx forums, you can find it here