Previous Table of Contents Next


6.3.1. Aims

During the 1982-1984 period, the aims for C++ gradually became more ambitious and more definite. I had come to see C++ as a language separate from C, and libraries and tools had emerged as areas of work. Because of that, because tools developers within Bell Labs were beginning to show interest in C++, and because I had embarked on a completely new implementation that would become the C++ compiler front end, Cfront, I had to answer key questions:

  Who will the users be?
  What kind of systems will they use?
  How will I get out of the business of providing tools?
  How should the answers to the first three questions affect the language definition?

My answer to Who will the users be? was that first my friends within Bell Labs and I would use it; then more widespread use within AT&T would provide more experience; then some universities would pick up the ideas and the tools; and finally AT&T and others would be able to make some money by selling the set of tools that had evolved. At some point, the initial and somewhat experimental implementation done by me would be phased out in favor of more “industrial strength” implementations by AT&T and others.

This made practical and economic sense; the initial (Cfront) implementation would be tool-poor, portable, and cheap because that was what I, my colleagues, and many university users needed and could afford. Later, there would be ample scope for AT&T and others to provide better tools for more specialized environments. Such better tools aimed primarily at industrial users needn’t be cheap and thus would be able to pay for the support organizations necessary for large-scale use of the language. That was my answer to How will I get out of the business of providing tools? Basically, the strategy worked. However, just about every detail actually happened in an unforeseen way.

To get an answer to What kind of systems will they use? I simply looked around to see what kind of systems the C with Classes users actually did use. They used everything from boxes that were so small that they couldn’t run a compiler, to mainframes. They used more operating systems than I had heard of. Consequently, I concluded that extreme portability and the ability to do cross compilation were necessities and that I could make no assumption about the size and speed of the machines running generated code. To build a compiler, however, I would have to make assumptions about the kind of system people would develop their programs on. I assumed that 1MIPS plus 1MB would be available. That assumption I considered a bit risky because most of my prospective users at the time had at most part of a PDP11 or some other relatively low-powered or timeshared system available.

I did not predict the PC revolution, but by overshooting my performance target for Cfront, I happened to build a compiler that could run (barely) on an IBM PC/AT, thus providing proof that C++ could be an effective language on a PC and thereby spurring commercial software developers to beat it.

As the answer to How does all this affect the language definition? I concluded that no feature must require really sophisticated compiler or runtime support, that available linkers must be used, and that the code generated would have to be efficient (comparable to C) even initially.

6.3.2. Cfront

I designed and implemented the Cfront compiler front end for the C84 language between spring 1982 and summer 1983. The first user outside the Computer Science Research Center, Jim Coplien, received his copy in July 1983. Jim was in a group that had been doing experimental switching work with C with Classes in Bell Labs in Naperville, Illinois, for some time.

In that same time period, I designed C84, drafted the reference manual published January 1, 1984 (Stroustrup, 1984a), designed the complex number library and implemented it together with Leonie Rose (Rose & Stroustrup, 1984), designed and implemented the first string class together with Jonathan Shopiro, maintained and ported the C with Classes implementation, and supported the C with Classes users and helped them become C84 users. That was a busy year and a half.

Cfront was a traditional compiler front end performing a complete check of the syntax and semantics of the language, building an internal representation of its input, analyzing and rearranging that representation, and finally producing output suitable for some code generator. The internal representation was a graph with one symbol table per scope. The general strategy is to read a source file one global declaration at a time and produce output only when a complete global declaration has been completely analyzed.

The organization of Cfront was fairly traditional except maybe for the use of many symbol tables instead of just one. Cfront was originally written in C with Classes (what else?) and soon transcribed into C84 so that the very first working C++ compiler was done in C++. Even the first version of Cfront used classes heavily but no virtual functions because they were not available at the start of the project.

The most unusual—for its time—aspect of Cfront was that it generated C code. This has caused no end of confusion. Cfront generated C because I needed extreme portability for an initial implementation and I considered C the most portable assembler around. I could easily have generated some internal back-end format or assembler from Cfront, but that was not what my users needed. No assembler or compiler back-end served more than maybe a quarter of my user community and there was no way that I could produce the, say, six back ends needed to serve just 90% of that community. In response to this need, I concluded that using C as a common input format to a large number of code generators was the only reasonable choice. The strategy of building a compiler as a C generator later became quite popular so that languages such as Ada, CLOS, Eiffel, Modula-3, and Smalltalk have been implemented that way. I got a high degree of portability at a modest cost in compile-time overhead. Over the years, I have measured this overhead on various systems and found it to be between 25% and 100% of the “necessary” parts of a compilation.


Previous Table of Contents Next