Home
Our Services
Programming Tools Business Unit
Compilers
Development of 'EC++' compiler for 32-bit RISC processor
Development of 'EC++' compiler for 32-bit RISC processor
Embedded C++ (EC++) is a trimmed down version of C++. It does include C++ features like multiple inheritances, namespaces, templates and RTTI which are not commonly used in embedded applications.
The project was planned such that only the front-end of will be developed for EC++; the back-end of the compiler can be common for C / EC++ input files. The project was planned and estimated such that even 30% of the C front-end can be reused for EC++.
| OS | Windows |
| Language/Platform |
|
| Development model | Incremental development model. |
| Quality validation tools |
|
| Test base |
|
The project was planned incrementally. The project had multiple incremental phases and the functionalities were distributed across the phases. More common features were placed on earlier increments and more specialized features were placed on the later increments. The incremental features were planned such that the compiler delivered at the end of each intermediate phase is usable with a set of restrictions (or unsupported features).
The first hurdle was to get a parser for EC++. We had to complete this first to start work on other modules. EC++ grammar by itself was ambiguous and so there is no direct way to write a parser to parse EC++ with tools like "yaac". "yaac" would give multiple (reduce-reduce) conflicts for EC++ grammar. Some open source implementations we referred used patches to the "yaac" generated code to resolve the conflicts. The solution we found was to use a backtracking version of "yacc" called the "btyacc". It provides a cleaner interface for the grammar itself to resolve the conflicts. Using this, we completed the EC++ parser. Stub functions were written for reductions related to EC++ constructs. The parser was tested manually using the states it traverses for each of the EC++ constructs.
Our next big task was to generate code for EC++ constructs. The team concentrated on 3 features at a time; with 2 members working on each of the features. Peer review was done on the artifacts. G++ (GCC for C++) was used as the reference compiler as it was considered most C++ compliant. There were variations in behavior of different compilers on how they process C++ constructs. We always stuck to what ANSI specifications said and what G++ did.
Generating code for some of the EC++ constructs like scope resolution, function overloading, virtual functions, in-line functions written inside class definition were really challenging. For each feature implemented the team prepared a detailed implementation notes covering the different case to be handled and its expected outputs. We called it the pre-design document. This greatly helped us identify all the aspects to be covered in implementation and gave lesser chances for a case not handled by implementation.
The testing team worked more closely with the development team. In parallel to developing the features, the testing team created tests to test specific EC++ constructs. When the compiler was in a position where regression test can be started, the team started the process of daily builds and smoke test. This process ensured that code stability is checked daily. Defects were identified early. The process also gave a greater visibility to the progress we were making.
The toughest challenge we faced was to interface the EC++ implementation with existing C compiler. There were multiple instances where interfaces provided by existing C compiler were not suitable for EC++ implementation. So we had to write our own version of the interfaces that implemented specific changes as required by EC++ implementation. This led to an increase in complexity and duplication of code to an extent. Due to this, the project was delayed as compared to initial estimate. At the end of the project the team realized that it would have been a lot cleaner if a whole new front-end for EC++ instead of reusing parts of the front-end of C Compiler.