telecom • networking • design

an EventHelix.com blog


Leave a comment

Map C switch and if statements to assembly code

This article covers the code generation for if-else and switch statements.

Switch jump table

The code generated for a switch statement varies a lot from one compiler to another. In fact, a given compiler might generate different code in different scenarios. The choice of the code to be generated depends upon the number and range spread of individual case statements.

Different cases of generation of a switch statement are:


Leave a comment

C Function Call to Assembly Translation – Frame Pointer Operations

Even though most programming is now carried out in high level languages, a good understanding of the generated assembly code really helps in debugging, performance analysis and performance tuning.

In this article, we will discuss the assembly code generated for function calling, parameter passing and local variable management. Frame pointer operations in a function call are described in detail.

C function call mapped to assembly - learn about frame pointer operations

We follow the lifecycle of a function call:

  1. Pushing parameters
  2. Invoking function
  3. Setting up the frame pointer
  4. Dismantling the frame and restoring the callers frame at function exit
  5. The caller popping the parameters.

C to Assembly : function calls and frame pointer operations


1 Comment

Optimize C and C++ Code

Optimize C and C++ codeWith the advent of mobile devices, optimizing code has become even more important. Faster applications not only improve the user experience, they also improve battery life.

Optimizing C++ and C Code discusses several techniques that will help improve the performance.

  1. Premature optimization is the root of all evil
  2. Adjust structure sizes to power of two
  3. Place case labels in narrow range
  4. Place frequent case labels first
  5. Break big switch statements into nested switches
  6. Minimize local variables
  7. Declare local variables in the inner most scope
  8. Reduce the number of parameters
  9. Use references for parameter passing and return value for types bigger than 4 bytes
  10. Don’t define a return value if not used
  11. Consider locality of reference for code and data
  12. Locality of reference in multi-dimensional arrays
  13. Prefer int over char and short
  14. Define lightweight constructors
  15. Prefer initialization over assignment
  16. Use constructor initialization lists
  17. Do not declare “just in case” virtual functions
  18. In-line 1 to 3 line functions
  19. Avoid cascaded function calls
  20. Prefer preincrement over postincrement
  21. Define move constructors in C++11
  22. Use hardware accelerators and SIMD hardware
  23. Use profile guided optimization


Leave a comment

Rules for managing header file includes in C++

C++ header file include rulesC++ header file management can be very frustrating:

  • Changing the the order of header files often results in difficult to track compilation errors
  • C++ project compilations take a long time due to complex header file inclusions

Here are a few rules to remedy this:

  • A header file should be included only when a forward declaration would not do the job.
  • The header file should be so designed that the order of header file inclusion is not important.
    • This is achieved by making sure that x.h is the first header file in x.cpp
  • The header file inclusion mechanism should be tolerant to duplicate header file inclusions.

An example of illustrates the header file inclusion rules:

Header file

#ifndef _a_h_included_
#define _a_h_included_
#include "abase.h"
#include "b.h"

// Forward Declarations
class C;
class D;

class A : public ABase
{
  B m_b;
  C *m_c;
  D *m_d;

public:
  void SetC(C *c);
  C *GetC() const;

  void ModifyD(D *d);
};
#endif

Source file

#include "a.h"
#include "d.h"

void A::SetC(C* c)
{
  m_c = c;
}

C* A::GetC() const
{
  return m_c;
}

void A::ModifyD(D* d)
{
  d->SetX(0);
  d->SetY(0);
  m_d = d;
}

For details, refer to: C++ Header File Include Rules


Leave a comment

C++ Internals: Mapping Inheritance and Virtual Functions to C

C++ to C conversionWe have already looked at mapping from C++ classes and methods to C structures and functions in a previous blog post. Here we will map inheritance and virtual functions to C code.

This blog post is based on the article mapping from C++ inheritance and virtual functions to C code. The contents of the article are summarized below.

Mapping a base class with virtual functions to C

A C++ base class with virtual functions requires extra logic to support the machinery for handling virtual functions. The following C++ base class….

class Shape
{
protected:
  int m_x;
  int m_y; 

public:
  virtual void Draw() = 0; 
  virtual void MoveTo(int newX, int newY);
  void Erase();
  Shape(int x, int y);
  virtual ~Shape();
};

…maps to the following C code.

typedef void (*VirtualFunctionPointer)(...);

struct VTable
{
   int d;  /* d and i are used in multiple inheritance */
   int i;
   VirtualFunctionPointer pFunc;
};

VTable VTableArrayForShape[] =
{
    { 0, 0, (VirtualFunctionPointer) pure_virtual_called_error_handler },
    { 0, 0, (VirtualFunctionPointer) Shape_MoveTo },
    { 0, 0, (VirtualFunctionPointer) Shape_Destructor }
};
struct Shape
{
  int m_x;
  int m_y;
  VTable *pVTable;
};

Points to note here are:

  • VTable structure used by the compiler to keep track of the virtual functions associated with a class.There is one instance of a VTable for every class containing virtual functions. All instances of a given class point to the same VTable.
  • The C++ compiler inserts an extra pointer to a vtable which will keep a function pointer to the virtual function that should be called.
  • The VTable pointer in the base class points to an array of VTables. The number of entries in the array of VTables depends upon the number of virtual functions in the class.
  • Note that a pure virtual function maps to function that will result in an exception.

For details refer to the article: Mapping from C++ inheritance and virtual functions to C code

Mapping an inherited class with virtual functions to C

The inheriting Circle class….

class Circle : public Shape
{
private:
   int m_radius;    // Radius of the circle

public:
   // Override to draw a circle
   virtual void Draw();   

   // Constructor for Circle
   Circle(int x, int y, int radius);

   // Destructor for Circle
   virtual ~Circle();
};

…maps to a new VTable array and a new struct:

VTable VTableArrayForCircle[] =
{
    { 0, 0, (VirtualFunctionPointer) Circle_Draw },
    { 0, 0, (VirtualFunctionPointer) Shape_MoveTo },
    { 0, 0, (VirtualFunctionPointer) Circle_Destructor }
};

struct Circle
{
   /* Fields inherited from Shape */
   int m_x;
   int m_y;
   VTable *pVTable;

   /* Fields added by Circle */
   int m_radius;
};
  • The inheriting class preserves structure offsets for inherited base class fields and the VTable array pointers.
  • A new VTable array is defined for the inherited class.
    • The pure virtual function entry has now been replaced with a call to Circle’s Draw function.
    • The entry for a function that is not being inherited is preserved (Shape’s MoveTo)
    • Shape class has a virtual destructor. The destructor vtable entry now points to Circle’s destructor.

For details refer to the article: Mapping from C++ inheritance and virtual functions to C code

Mapping a virtual function call to C code

A virtual function call like…

 pShape->Draw();

…is replaced by a call through a virtual table function pointer.

  (pShape->pVTable[0].pFunc)(pShape);

Explore More

We have covered basics of inheritance handling here. For details about constructor and destructor definitions and vtable array pointer initialization refer to the article:  Mapping from C++ inheritance and virtual functions to C code.


2 Comments

C++ Internals: Mapping from C++ classes and methods to C structs and functions

Mapping from C++ to C code

C++ internals can be better understood by mapping them to corresponding C code.

Refer to the article mapping from C++ classes and methods to C structs and functions.

The contents of the article are summarized below.

This pointer maps to an additional parameter

A C++ method maps to a C method with an additional this pointer. For example, the UpdateX method C++ method…

void A::UpdateX(int newX)
{
  if (g_y != 0 && m_x < newX)
  {
    m_x = newX;
  }
}

…translates to the following C code:

void A_UpdateX(A *this_ptr, int newX)
{
  if (g_y != 0 && this_ptr->m_x < newX)
  {
     this_ptr->m_x = newX;
  }
}

Complete article: Mapping from C++ classes and methods to C structs and functions.

A class maps to a struct with associated methods

A C++ class is equivalent to a C structure with a class methods. The following class…

class A
{
private:
  int m_x;
  static int g_y;
  int m_z;

  // Should be invoked when the object ends
  void InformEnd();

public:
  A(int x);
  ~A();
  void UpdateX(int newX);
  static void UpdateY(int newY);
};

…is represented as the C structure with functions.

  • Methods have a corresponding this pointer.
  • Static methods are functions that do not get an additional this pointer.
  • Static variables map to global variables.
struct A
{
  int m_x;
  int m_z;
};
int g_y = 0; /* Represents static variable */
A *A_Constructor(A *this_ptr, int x);
void A_Destructor(A *this_ptr, BOOLEAN dynamic);
void A_UpdateX(A *this_ptr, int newX);
void A_UpdateY(int newY); /* Represents a static method. */

Complete article: Mapping from C++ classes and methods to C structs and functions.

Constructor representation in C

In C++, objects may be allocated on the heap or the stack. This has implications in the mapping from a C++ constructor to an initialization function in C.

A::A(int x)
{
  m_x = x;
  m_z = 0;
}

The mapped constructor takes an additional this pointer. A NULL is passed as the this pointer when the object has to be allocated on the heap. A valid stack address is passed when an object is on the stack.

If a NULL pointer is passed to the construction function, it allocates memory before performing the initialization.

A *A_Constructor(A *this_ptr, int x)
{
  /*Check if memory has been allocated for struct A. */
  if (this_ptr == NULL)
  {
    /*Allocate memory of size A. */
    this_ptr = (A *) malloc(sizeof(A));
  }

  /* Once the memory has been allocated for A, initialize members of A. */
  if (this_ptr)
  {
    this_ptr->m_x = x;
    this_ptr->m_z = 0;
  }
  return this_ptr;
}

Complete article: Mapping from C++ classes and methods to C structs and functions.

Destructor representation in C

Destructors also deal with deletion of stack and heap objects.

A::~A()
{
  InformEnd();
}

If the object was allocated on the heap, a boolean is passed to signal to the construction function that the memory was allocated dynamically and needs to be freed.

void A_Destructor(A *this_ptr, BOOLEAN dynamic)
{
  InformEnd(this_ptr);

  /* If the memory was dynamically allocated for A, explicitly free it. */
  if (dynamic)
  {
    free(this_ptr);
  }
}

Complete article: Mapping from C++ classes and methods to C structs and functions.