Tools • 43:18
Learn about Apple's implementation of the GNU C Compiler (GCC) and the migration towards GCC Version 3. Enhancements include improved code generation, reduced compile time, better IDE integration, and many other new features.
Speaker: John Graziano
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Welcome. My name is Godfried E. Giorgi. I'm the Technology Manager for Development Tools, and I'd like to welcome you to our session on compiler developments at Apple. As we drill deeper today into our tools and into the development of our tools, it's proving to be a very, very interesting day with the questions we've seen so far. At that note, Let me introduce John Graziano, the manager of the Mac OS X Compiler Development Group.
[Transcript missing]
Today we're going to talk about GCC 3.1, which is the next compiler coming for Mac OS X. We'll touch on some of the new features. We'll also talk at the end about converting projects, some issues you might encounter. And we'll spend a lot of time talking about developments we've done in code quality and compile time. So how many people actually use GCC for Mac OS X development? How many people here work with Code Warrior? How many people here actually work for Code Warrior.
I should probably talk about that slide going back. The GNU C Compiler, for those of you that haven't seen it before, it's free software. It supports ANSI C, C++, and Objective-C. There's also a bunch of other front ends, including Ada, but these are the ones that we focus on.
It has a very robust C++ implementation because there's many years of work and testing on this. There's just billions and billions of lines of code that have gone through this compiler. It's used as a reference compiler on many systems for many developers, and we use it on Mac OS X because, frankly, it compiles all of Mac OS X. When you start up OS X, start the finder, you're running mail, pretty much everything you see on Mac OS X is built with GCC3. at this point.
So the latest work in 295, what you got on the April Developer Tools CD and what's shipping on Mac OS 10.1. 295 is the default compiler on 10.1. It's the default compiler on the April Tools CD. We've made some improvements to the code generation, including code quality and reduction of memory footprint, which, as you've seen if you attended the performance tools session, is a critical feature for us. We added Objective C++, and we put in two-level namespace the same way it works with Mac OS 9. So let's talk about GCC 3.1.
So there's new features in the compiler. The community has added C99 compliance. We have C++ ANSI compliance. We've integrated the preprocessor, so we no longer have a separate process that runs to do the preprocessing. There are more optimizations. The optimizations that are there have been improved. And most specifically for C++ programmers, there's a new ABI.
So some things that we've added to 3.1. We've actually gone in and made further improvements to the code generation. We've added a new pre-compiled header scheme for C++, and we'll talk a lot about that in future slides. We again have integrated our Objective C++ support in with the Objective C support that comes with the GNU C Compiler. And of course we've added our MachO support.
So, we're saying this in every session, but I want to make it clear: wait for Jaguar to ship before shipping any products with 3.1. It's a beta compiler right now. We're correcting some things, including a couple C-ABI issues having to do with Bool that are going to be critical for making your apps run well on Jaguar. So wait before you ship anything until we ship the final version.
So let's talk a little bit about Objective-C++. I stood up here last year and Zem Lasky stood up here last year and we talked about what we were going to deliver in the next tool CD for Objective-C++. Well, we delivered that and people have actually been using it.
So for those of you that aren't familiar with it, Objective-C++ is a combination, a syntactic combination of C and Objective-C. It allows us to integrate C++ code with Cocoa applications. That's the intention. That's why we did it. So you could take your legacy C++ code and you could integrate it with your C++ code. You could move it over to Mac OS X and you could put a nice Cocoa UI on top of it.
We've added a new file extension, .mm, so if you see projects with .mm in it, that means that they are Objective C++ files. We also used to have the .M back in the old Next Step days, and of course on HFS that doesn't work too well. So we still support it, but we discourage the use of it because it collisions with the lowercase m, which is used for Objective C files. So we allow you to do a lot of mixing with Objective-C and C++. You can mix declarations. You can have Objective-C objects point at C++ objects. You can have C++ objects point at Objective-C objects. And you can invoke Objective-C message sends anywhere in a C++ expression.
So there are some restrictions that we have. First and foremost, you cannot mix the object hierarchies. So the object models are kept completely separate and, as Zem likes to say, mutually oblivious. And we did that intentionally, first of all, because it would be really hard to mix them together, and also because it introduces a lot of corner cases that we just don't want to have developers have to think about. It's much simpler to keep them completely separate. Objective-C objects descend from Objective-C objects. C++ objects descend from C++ objects.
C++ classes, of course, cannot be receivers of Objective-C messages, and vice versa. You can't invoke a function in Objective-C as you would on a C++ class. And finally, you can't statically allocate new or delete Objective-C objects. You use the same alloc init paradigm that you're used to with Objective-C.
So it's for real. We've been shipping a compiler with it for almost a year now. And we have actual apps that are shipping on the system that have Objective C++ in them. Project Builder has Objective C++ in it. IDVD has Objective C++ in it. There's a lot of third-party applications that are also shipping with Objective C++ in their code base.
So, code generation. Let's talk a little bit about how we measure code quality. The first thing that we use is real-world code. We plug a lot of code through this compiler. Again, we are the compiler for all of Mac OS X, so we have a lot of things that we can look at and test to see how we're doing with code generation.
We use benchmarks like everyone else. It's a good way to isolate compiler problems. And finally, we test ourselves against other compilers. We look at Code Warrior. We look at Mr. C, which a lot of people had high regard for on Mac OS 9. And we look at GCC 295 to see how much we're improving the code generation from one release to the next.
So, some real-world code that we look at, and the reason that we use real-world code is that we can get at large components of the operating system and see overall how the compiler is doing. It allows us to measure big factors like memory usage, system usage, how much we're accessing the disk. We have large chunks of code. We can measure things like code size a lot easier than measuring a simple benchmark because the code size tends to accumulate overall.
Some of the real-world code that we use, well, we look at QuickTime, see what frame rates we get. We look at iTunes for the encoder, see how quickly we can encode and decode your music. We look at the Mach kernel and run benchmarks on that for networking and file system access and so on and so forth. We look at Quartz and OpenGL. And we look at the Java VM. That's just a subset of some of the things that we look at when we're measuring our code quality on Mac OS X in general.
So we also rely a lot on benchmarks. One of the problems with real world code is if you find that, oh, you know, QuickTime is running, you know, 4% slower. There's a lot of code in QuickTime, so it's very hard to track down exactly where the compiler is slowing you down. So benchmarks make it easier to isolate some of these code gen problems.
A benchmark is just a collection of CPU-intensive routines, something preferably that can be built from multiple platforms by multiple compilers so that you can get a lot of axes of comparison. Each test will hopefully target a subset of compiler code generation, either integer code generation, floating point code generation, and so on. We use it to measure our basic optimization techniques to see how well we're doing.
So some of the benchmarks we use. This is sort of becoming the standard, CPU2000, which was formerly known as SpecMarks. It's a big test. As an example, one of the tests in SpecMarks is GCC itself. They test how quickly an older version of GCC can run a bootstrap. So it's a very big test. A lot of system interaction, a lot of calls that the compiler doesn't control into libraries. So it's a good test of an overall system, but it's not the best thing for tracking down a particular code gen issue.
We've looked at ByteMarkz. The back-end guys are not big fans of ByteMarkz. It's kind of an older test. A lot of people have stopped using it. It's easy to manipulate this to get an inflated score on ByteMarkz. You can do a lot of optimizations that don't have any application in the real world that don't make Mac OS X better, but make your ByteMarkz score better.
And also, of course, it doesn't have things like AltaVec on it, so you can't test your AltaVec performance by using ByteMarkz. And we have one called Skidmarks that I'm going to talk about a little more in general, which we rely a lot on. It has been incredibly helpful in us in helping us improve the compiler.
So, if you take an overview of SkidMarkz, it was developed by Apple's hardware group. If any of you were at the performance tools talk yesterday, you saw some of the guys who developed the SkidMarkz benchmark. We actually took samples of real world code that was running on the Macintosh so that we could actually have targeted attack at the code generation problems that affect you on a day-to-day basis.
They're very small tests, much smaller than SpecMarkz. They stay in cache. They don't have a lot of system calls. So, we can actually measure how we're doing on the production of actual code. And it's broken up into three categories of tests. We have integer tests, we have floating point tests, and we have AlteVec tests.
So let's look at what's actually in SkidMarkz. We have an MPEG-2 encoder that we test. We have a pixel blender that we use in Final Cut Pro and iDVD. So again, shipping code that goes out to you, we're making sure that we optimize it as best we can. We have two encryption routines which appear in our security software. For the floating point test, we actually have a sample of Quake 3. We're testing one of their math routines to see how we do. We have, of course, a standard fast Fourier transform and a volume integration.
And then we have Altevec tests. We have gravity calculation called Galaxy. We have something called Inverse Discrete Cosine Transform, which somebody told me once what that meant, but I know that it's used in QuickTime in the codex to generate images. And again, we have multiplication of really big numbers, which is one of the things that scientific computation wants to use Altevec for.
So, let's see where we were. This is where we were last year when we were talking about GCC 295. So, and just to note, smaller is better. So, in 295 on the integer tests, Code Warrior 7 beat us by about 5%, and Mr. C on Mac OS 9 beat us by 33%. Not very good. On Floating Point, we're in a similar state. Code Warrior 7 was beating us by 18%. Mr. C was beating us by 12%.
And then finally on our AlteVec test, Code Warrior beat us by 19, Mr. C beat us by 15. So of course, this is something we weren't too happy with and we wanted to go ahead and try and fix this in the next version of the compiler. So overall, what we're seeing is that Code Warrior was 13% ahead of us on just general code gen, and Mr. C was beating us by 21% on general code gen.
So what did we do to go fix this? Well, the first thing we do is we run something called Nullstones. And Nullstones is kind of a benchmark for the compiler where it tells you what optimizations are actually in the compiler and how well they're doing. So we can test individual optimization passes, see that, oh, it's not doing the scheduling the way we expect it to, or it's not doing alias analysis the way we expect it to.
Again, as we've said, we do head-to-head comparisons with compilers. As you see, Code Warrior was doing better code gen on a lot of things. Mr. C was doing better code gen on a lot of things. It's very instructive for us to look at what they're doing, how they're getting those numbers, so we can see what we can put into GCC to make it better.
This involves a lot of inspection of assembly files. A lot of times I walk past the offices of the back end guys and I see them scrunched up looking at these lines and lines and lines of assembly output trying to figure out where this one variable is hanging out in an inner loop and whether we can take it out.
And then finally, we just sit and look at compiler source code and see if there's any bonehead bugs in the back end of the compiler source code. Again, this is not magic. It's just a lot of work and it's a lot of qualification. And every time we make a change to code generation, we have to run all of Mac OS X through the compiler again to make sure we didn't mess anything up.
Let's look at how we were doing in 3.1. Well, one thing we've added is a forward inliner. This came from the community, but it lets us do more and better inlining. And a lot of times this lets us benchmark a lot better, and in some cases it'll let your code run a lot better. But as we'll talk about a little later, you need to be careful with the inliner.
We've added something called dynamic non-pick or non-position independent function calls. I wanted to have a little propeller head beanie for this one, but for those of you that aren't compiler heads, basically in Mac OS 10.1 we generated all of our code as position independent code, which meant that we had to do a little bit of extra instructions every time we made a function call in order to find the address of the function. Well, one of the things that we noted was that we had to do a little bit of extra instructions every time we made a function call in order to find the address of the function.
When you generate an executable, it doesn't have to be position independent. It doesn't have to be able to slide its address around the way a shared library or a library would. So we don't have to have position independent code. What this lets us do is it removes one level of indirection for our library calls, and it saves us two loads per call on average.
For small functions, for example, on a Hello World, I actually ran this on Hello World and noticed that it reduced, the calls, the instruction stream by eight instructions for a simple call out to a function. So if you have a lot of functions that just call out to other functions or call out to a couple functions, you should see a good win on this. We've added AlteVec and floating point optimizations.
And of course, we've just continued and continued incremental improvement of the compiler. The reason I emphasize the incremental improvement of the compiler is because we build every week all of Mac OS X with this compiler. So I sort of think about it as constructing the 747 in mid-air. You have to keep the compiler running for every build of Mac OS X while you're making these code gen improvements.
So let's look at how we did. So this was the graph we got for the integer processing. And GCC 3.1 now comes in here. It's 28% improvement over 295. beats Code Warrior 7 by 22%. Mr. C is still a little bit ahead of us, but we're working on that. On the floating point processing, We have a 20% improvement over 295. We're pretty much in a virtual tie with Code Warrior. And with Mr. C, we're beating it by 7%.
And on AlteVec, 28% over 295. This was the biggest complaint that we got out of 295 was that our AlteVec code generation was really, really terrible. And Dale Johannesson is one of the guys on my team and he did a great job in making our AlteVec code the best for Mac OS X. So overall what you see is GCC 3.1 on our internal benchmarks is giving us 11% over CodeWarrior 7, is giving us 4% on Mr. C, and is beating GCC 295 by 25%. It's a 25% improvement in code gen over 295.
So, what you can do with CodeGen. First thing, and I always have to say this, is optimize your code. We get a lot of bugs coming in from external and internal users that say, "GCC's code gen is 50% slower than my other compiler." And we find out that they're not passing an optimization flag to it.
GCC's code gen for unoptimized code is fairly unoptimized. So... So one thing that we recommend is a new flag called -OS. It was actually on 295 but didn't work that great. I'll talk a little bit more about -OS. But -OS is the flag that you want to pass in to your projects when you don't have any other reason to change the optimization. If you don't know what optimization to put on your code, use -OS.
And measure. If you have performance-intensive parts of your code, measure them. Use the performance tools that you saw yesterday. In a lot of cases, the optimal settings depend on your code. There's absolutely no way that we can give you a generic set of optimization switches for everyone's code. It's going to depend on how you're using C++.
It's going to depend on how many function calls you have, how many loops you have, so on and so forth. There may be cases where inlining is great for you. There may be cases where inlining is terrible for you. It depends on what your application is actually doing.
Let's talk about Dash OS, optimized for size. This is something that we're pushing really hard internally, and we want people to use it externally. As we've talked about, one of the key things for Mac OS X performance is memory footprint. If you want your app to start up quickly, one of the ways to have it start up quickly is to have it load less code off the disk.
So, -OS produces the smallest binary size for most executables. In fact, for all the executables that we've tried, it produces the smallest binary size. It's roughly equivalent to -02. We turn off a couple of things. We don't have loop unrolling. We don't schedule your code, which can lead to bloat or do register renaming.
And we have limited inlining. We don't do any inlining unless you actually include the inline keyword. So, what this will do is, you know, there may be a few optimizations that are missing out of -02, but you more than make up for that if you just save one page off the disk when your app starts up or when your app has to be swapped in again. Also, because your code is smaller, more of it is going to sit in the on-chip cache. So, you're going to get better performance through that.
The other thing I want to talk about is -mdynamicnopic. And this again is a propeller head slide. But people who are using Makefiles especially for building executables, either tools or applications, you want to know about this. It's new in GCC 3.1. It generates indirect, non-position independent function calls.
And the big thing is it reduces your code size by 10%, and it increases your code performance by 10%. This is great for applications that use our toolboxes. The applications that most people are writing are going to be heavily dependent on a lot of library calls, a lot of system library calls, and this focuses right on those call sites and makes them more efficient.
For people using Project Builder, on the Jaguar CD that you have, it's the default. You just hit Build and you get this flag passed in. If you're using Makefiles, you're going to have to add it to your compiler switches. Again, I'll emphasize, use this only on executables. If you're building libraries, if you're building shared libraries, anything like that, frameworks, you can't use this because the frameworks and libraries can come in, and bundles and plugins as well, can come in at any address. The code has to be position independent.
So one thing I want to talk about also is -03. We found that a lot of people use -03, and when we asked them why they felt they needed -03, the general response we got was, "Well, 3 is more than 2, right?" It's got to be better. Well, that's not always the case. The big thing that you get with Dash03 is it turns on automatic inlining of your code.
So before, if you're running with DashOS, it would obey the inline keyword. If you're running with Dash01, you don't get any inlining. But if you're running with Dash03, you get inlining at the discretion of the compiler. So you may get some surprising results, especially since the inline keyword only uses a hint. It's kind of like the register keyword at this point.
And the limit set by the inlining is measured in internal data structures of the compiler. It's about as deep of a flag as you can pass to the compiler. The inline limit, I think, by default is about 600, but it's measured in nodes of the compiler tree, and it really doesn't have... it doesn't have any direct meaning for your code.
The only thing that it has is that you set it higher, you get more inlining. You set it lower, you get less inlining. So it's something that you have to play with. But the key is, if you run at Dash03 and you set an inline limit very high, you could get very, very bloated code.
You know, 40% bigger, 60% bigger than the code that you would have with Dash02 or DashOS. So this is something that you have to do. So this is something that you have to do. This is something that you have to be very, very careful about. If you're running with Dash03, you want to look at the difference between your code at Dash03 and your code at DashOS. If you have some performance-intensive routines, you may still want to get some inlining. But if you notice that DashOS, you can obey the inline. You can have it obey the inline keyword. You can actually hand inline those if you want to get better performance out of them.
So, if you're using Project Builder, a lot of this is taken care of for you. The MDynamic no-pick is passed by default on executables. -OS, if you make a new project, is going to be your default optimization setting. And of course, there's some compiler switches that you can control for setting the optimization, for setting the debugging symbols. There's a nice GUI for this.
Let's go on and talk about build time. This is something that has been a key feature for us. A lot of people have complained about GCC's build time, especially for C++ because we didn't have a precompiled header solution for C++. We've been looking at C++ build time, and we actually looked at the most popular C++ framework out there, which is Power Plant, to see how we did. GCC3 takes 25 minutes and 40 seconds out of the box to build Power Plan on our fastest CPU. Now, for those of you that don't know where Code Warrior is on this, they're there. 41 seconds.
So we always go back to this and look at it and just say, how did they get so fast? So we've been asking ourselves, how do they get so fast? Where does the time go in GCC3? Well, we have a little bit of overhead. We run separate processes, so we pay a little bit there for starting up the processes.
Then, we spend a whole bunch of time in every compile Processing headers, just parsing headers, looking for headers, just doing a bunch of header processing. After that, we have source code processing, code generation, a little bit of assembler, and a small amount of link time. And that all adds up in Power Plant to 25 minutes and 40 seconds.
So, what happens when you're parsing headers? First off, you spend a lot of time in I/O. You're reading files, and not only are you reading files, you're looking for files. You're searching the disk for files. And because we run the compiler as a batch process, it has to research every time it starts up.
We're doing the pre-processing, which can be costly depending on how many macros you have. And of course we're parsing declarations, which we pay for in a couple of areas. We pay for, and of course the CPU uses just the compiler doing its computations. And in memory allocation, especially in C++ because the compiler has to allocate a lot of memory to handle all of the declarations that we process. It's a hundred thousand lines of declarations in Carbon alone. And we have to process all of those for every file you build.
So, people are asking, "What about CPP Precomp?" This is something that we leverage heavily on 295 in our C and Objective-C. It's a precompiled mechanism that we brought over from Next, and it stores all of your headers in tokenized form. And one of the best parts of it, and one of the reasons why it is so fast and gets you such a good result on C and Objective-C, is that it selectively unparses only the declarations that you reference and passes those to the compiler.
So, it's a much smaller set of code that you build for every translation unit. It has good project builder support, but the one problem is it cannot contain C++. We've done some work to get CppPrecomp to kind of live in the C++ world, but you can't precompile any C++ code into CppPrecomp.
So we came up with a new mechanism we call the persistent front end. And the persistent front end saves the entire front end state to disk. You basically go all the way through the parse, we get to the end of the parse, and we dump that out to disk.
And then what we do is on subsequent runs of the compiler, we map that in at a known address. This lets us get a couple of things for free. One, we don't have to go through and swizzle all the pointers in the data structures. They just work. And two, those pages that we've mapped in will stay resident from run to run of the compiler. So we've cut down all the I/O that we need to do to bring in these pages from one run of the compiler to the next.
Supports all C flavors, all four of them: C, Objective-C, C++, Objective-C++. It gets all the constructs. It uses the actual compiler to do its work. So there's no difference between running your code with the PFE and running your code without the PFE in terms of semantic processing. You should see absolutely no difference. In CPP PreComp, we had a couple of things that were different because it was a separate application outside of the compiler world.
Let's see how we do with the PFE. Here's where we were. GCC3 was at 25 minutes and 40 seconds. CodeWarrior's building power plan at 41 seconds. The PFE comes somewhere in the middle. We get down to 4 minutes and 21 seconds. That's a 6x improvement over GCC3 out of the box.
So this will get, for big C++ applications, this will get your turnaround time into the realm of reasonable. We're still not at the code where, oh my god, that's so fast. But we're at the point where you can actually get reasonable turnaround time out of this. A compile time improvement up to six times faster with GCC 3.1 using the persistent front-end.
So where do you set this up? Anders Bertelrud at 2 o'clock today is going to go into much more detail on how you use the persistent front end from Project Builder. But there's a couple things that I wanted to point out here. First of all, you need to set up a prefix header.
How many people have set up a prefix header in their projects in Project Builder? You know how to do this. You basically just take a header, you let it import a whole bunch of other headers, and then you click the Precompile button. It's the same thing that you do with CPP Precomp in the current version of Project Builder. Now, we have one more thing that you have to do in this version that you've got on the Jaguar CD.
Ooh, new compiler UI. This is not the new color scheme for Project Builder. But down here you have to actually add a custom build flag and I promise you and the PB team promises you that we will have UI for doing this. But you have to say use GCC3 PFE support, set that to yes on the Jaguar CD.
If you don't do this, you'll get the old CPP Precomp mechanism because we wanted to bring that support forward in the compiler for people who are using it and like it in Objective-C and C. You can still use that with GCC 3.1. But if you want to try out the new PFE, you set this to yes, have a prefix header, hit precompile, and you'll get the PFE.
So, today, we've sped up raw header processing 8 to 10x. We've given full support for C++, Objective-C, Objective-C++. And we've given you overall build speed increase as much as 6x. And we've actually seen this. This is not just some rigged up thing. We just saw that the Finder team is getting 6x build speed ups with GCC3 and the PFE. Power plant, six times.
We've seen some of our other applications that we're converting over to the PFE, they get in the realm of six times. So this is something, this is not really a your mileage may vary. You may see something, depending on how your app is structured, depending on how much you put into the precompiled header, somewhere on the order of four times to eight times. But it's definitely a significant improvement over GCC3.1 out of the box and 295 compile times.
So, how do you move on to GCC 3.1? There are some changes in the compiler that are going to affect you and they're going to especially affect C++ programmers. You've got a new STL and lib standard C++. Changes to things like iterators, exceptions, there's the whole support for I/O stream in there with the locales. We have stricter ANSI compliance. This is going to bite some people, especially if you're used to using 295 or Code Warrior. We catch a few more things in terms of ANSI compliance.
We have better error checking. This is good and bad. The bad part is you may get more errors in your code or you may get more warnings in your code. The good part is a lot of those warnings are real and a lot of those errors are real. We've actually caught a lot of bugs in Mac OS X just by running them through GCC 3.1 and correcting build failures.
And of course, we have a new C++ ABI, which is going to have implications for how you build your code. So let's talk about the first one, C++ ABI. So if you see this problem where you're building a C++ application, you're linking against a library, and the link is just failing with many undefined symbols, especially symbols that you recognize from your library, the problem is that you probably forgot to compile a library with GCC 3.1.
The entire C++ stack that you're running needs to be built with 3.1. We've changed the name mangling, we've changed the Vtable layout, everything. So it's just not going to work to link a C++ application against a 295-built library. You need to have them both built with GCC 3.1.
Also, namespaces. GCC 3.1 strictly adheres to namespaces. If you see that your compile fails with some symbol not in scope, the cause may be that all C++ library classes are now in the standard namespace. To fix this, you prefix those library references with the standard colon, colon, or you use the using standard directive. This should clear up those symbol errors.
So we have STL changes. This is one that we ran into a lot when we were trying to get Mac OS X rolled out onto GCC 3.1. The problem here is that the exception in the STL has added empty throw specifiers to its constructors and its destructor. And if you have a subclass, or if you're subclassing from L exception in the STL, you need to add those same throw specifiers so you have the same declarations in your code. So if you put on an empty throw specifier, when you see this error, this should clear up this problem for you.
So finally, linking with lib standard C++. If you see that your link is failing with strange undefineds like underbar GXX personalities, things that you've never put into your code or into your libraries, it probably is that you're failing to get a link against lib standard C++. So the easy way around this is to use the C++ command.
We have a lot of ways that you can invoke the compiler from the command line, a lot of ways that you can invoke it from Project Builder. Project Builder will handle this automatically for your C++ builds now. So if it sees that you have C++ files in your project, it will link using the C++ command rather than the CC command. So this is the easy way to get all of the default behavior that you want on your link line is just to link with C++.
A couple of other issues that you might encounter. Type agreement is strictly enforced, so if you're passing in const where there is no const or vice versa, you're going to have to cast that. We caught a lot of issues with casting where GCC295 led it through. GCC3.1 is going to flag that with an error.
Here's one that we've been wrestling with for a long time. We fixed a bunch of bugs in this area, but since CPP Precomp is something that is mostly applied to C and Objective-C, we haven't gone all the way to having CPP Precomp understand the new STL. There's a lot, lot more stuff in the new STL, and there's a few things that CPP Precomp just flat out doesn't like.
So if you're using CPP Precomp with your C++ code, I definitely recommend that you go over to the Persistent Frontend. It's going to get you a lot better performance because you can take your C++ code, your power plant headers, your stable headers from your project, you can put them all in a precompiled header, and you can leverage a lot more of the code. You can put the STL headers into the precompiled header, and you can get a lot more of a win in compile time out of that.
And finally, C++, the C++ compiler, now recognizes operator names. So you can actually type in and, not eq. These are all recognized as keywords now, xor and or and a few others. These are all recognized now as keywords in the compiler. If you find out, if you want to name your variables and or not eq, you can pass in f no operator names and that turns that off. So this is a couple things that may bite you as you're converting your code to GCC 3.1.
So, the bottom line is that C++ projects are going to require some code changes. The read we got from the Finder team, they were sort of one of our early adopters, is about 98, 99% of their stuff just built and they had to make a few tweaks in terms of adding some CAS, in terms of adding some using directives, and so on and so forth. But it's not, we're not talking re-engineering here, we're just talking about bringing your app more into the compliance that GCC 3.1 is expecting. C and Objective C should just work.
You should just be able to take your code with your C files, switch over to using GCC 3.1, hit build in Project Builder, and it should just go. Anybody sees any problem with that, they should let us know because we definitely have worked to make this as seamless as possible.
So we're still working on this. What you have is not the final copy for Jaguar. The first thing that's happening is we're giving you a full sync with the GCC 3.1 release. I saw Stan Shebs walk in late to this talk, and I'm sure that's what he was working on, is getting the latest build with the full merge of the GCC 3.1 release.
We're making further code gen improvements. We didn't stop just to cut the CD, so we're putting in further code gen improvements. We're making some adjustments for speed, some improvements in speed, but mostly what we've been focusing on since the compiler that you have is size, especially C++ code size.
A lot of you guys will see when you run this compiler that your C++ binaries are going to be a little bit bigger than they were in 2.9.5. We're adding a lot of features, a lot of code gen improvements. We're going to bring that back in line with what 2.9.5 was.
We're working on tuning the PFE. The PFE at this point is basically a big architectural change. We've taken the back of the front end, we saved it out to disk, we loaded it back in. And that was our big win. We got 6x out of that. Now we're looking at doing some of the harder and more incremental things, tightening up the data structures, tightening up the algorithms inside the persistent front end, inside the front end of GCC itself, and getting you better turnaround time even than we're delivering today. And finally, expect to see great PFE support in Project Builder. Expect to see just point and click and you're off and running with the new PFE as opposed to CPP Precomp.
So, GCC 3.1, you get better C++ compliance, you get improved code quality, and you get You get other things. Faster compile time. And use it now, but ship with it on Jaguar. Again, don't ship with it now. So just one more pointer to the technical documentation. Developer documentation is in /developer/documentation/devtools. There's stuff on the compiler.
There's the GCC release notes. There's write-up on the preprocessor, on the debugger, and also a brand new book on the Mako runtime, which should be very interesting to anybody who really gets into reading about the Mako runtime. So at this point, I think it's time for Godfrey again.
Thank you, John. Testimony to a lot of work. A big hand for John and his team who are all in the front row here. We intentionally wanted to leave a lot of time for questions during this session, so just a very brief look at the roadmap for the rest of the day.
This afternoon, we have our session, Delivering with Project Builder, which talks about how to get the most out of Project Builder, utilize the build system to great advantage. We have the Development Tools Feedback Forum in Room J1 right next door. And then we close the day with Debugging in Mac OS X. And I hope to see you all there.
Contacts for Development Tools. I'm always a primary contact if you have business issues, if you want to talk to people on the engineering team in person, I can always help to facilitate that. We have a mailing address, which you've seen in many of our Tools sessions, for the Development Tools Engineering feedback. This talks to the managers and key people throughout the organization. And also for bug reporting.
We want to hear your bugs. We have a project builder users mailing list and several other development mailing lists where people talk about problems they've run into. What we need to see is things that are identified as bugs reported to us with Bug Reporter so that they're on our map, so they're on our priority list.