Course: COS 320
Instructor: David August
Description of Course Goals and CurriculumThere are two related goals in the course: making something that correctly translates human-readable code into assembly language and making that code more efficient. The assignments focus on the former; the lectures and exams focus on the latter. As far as optimization, the professor splits his time between analyzing graphs of "basic blocks"—small units of code for which running the first instruction requires that every other instruction in the block will also be run unless there is an error—for special relationships between the blocks and considering simple rules that reduce the number of instructions required for the code to work. Some hidden teachings I learned from the course related to other branches of computer science. Compilers are extremely systematic translators; the majority of the optimizations in COS 320 never cause the program to run improperly. There are such optimizations, and August will refer to them regularly but not require you to learn a lot about them (although they appear in the last (and hardest) assignment), but even in these cases, the compiler MUST realize that the program made a mistake and correct it automatically. If the program errs once per thousand lines of code, it will very likely err in every run of a long program, which is unacceptable. This is good practice in industry and will serve you well. Similarly, some of the ideas of reducing a large set of possibilities to a simplified set of "tokens" and then an "abstract syntax tree" before expanding it again to a complete program is useful in numerous applications from immunology to graphics.
Learning From Classroom InstructionProfessor August is prominent in the field of compilers and highly responsive to advice. It's normally a small class, so he actually cares about ways you think he can make class more instructive and enjoyable—I made one suggestion, and he implemented it. He explains analyses and optimizations carefully. He makes it look easy, and although most of the ideas early in the course are straightforward, it's important to be able to apply them accurately without external aid. I would suggest practicing each at least once before each exam. It is easy to walk through an analysis with all the steps in front of you; it is far harder to remember all the details without help, especially on a timed exam. During class, it's critical to ask whenever something is unclear. He welcomes questions (and uses it as extra credit) since they make the material clearer for everyone. It's also useful to try to solve the sample questions as he does or, ideally, before he does and check your answers as he goes. He does make mistakes sometimes, but even so, it is unlikely that you will end up at the same answer if you don't understand, and he will help clarify.
Learning For and From AssignmentsThe main idea to keep in mind is that, as far as creating or modifying code in LLVM (the "language" we use for most of the course), adding an instruction to a basic block is adding a new line of code immediately after the previous one. Adding a new basic block is asserting that there is a jump statement somewhere, whether from the bottom to the top of a loop, around an if statement, or in a function call. Specific advice for the first assignment: This assignment is very simple. It was also my second-worst grade because I did not read the "Fun" syntax provided carefully enough, so I asserted that some valid variable names were invalid and vice versa. Be careful with this. Pay attention with the third and fourth assignments. The third isn't too complicated, but unlike the first two assignments, understanding the third and fourth assignments will be very helpful for the last two. Note that this also means that you won't have an idea for how hard the class is from the first assignment. The third assignment is also exceptional for teaching skills that apply in other contexts. Start all assignments (but especially the sixth) early. August is willing to grant extensions, but you shouldn't rely on this, especially with programs as hard to debug as compilers. Keep in mind that there are many variations on how to do some of the assignments, although there are certain features that have to remain constant. Finishing something in an inefficient way will still get you full credit—as long as it ends up with the same result. Since the assignments are auto-graded, it is important to be careful with ensuring that the end result is the same even if the intermediate steps are different.
External ResourcesProfessor August is a clear and knowledgeable lecturer, but he prefers not to spend too much time outside of class. Although he is willing to meet with you, he tries to handle you efficiently, and he sometimes did not go to office hours. That being said, he responds relatively quickly and reliably to emails, although this may mean telling the preceptor to handle your problem—that tends to work. Professor August provides resources for LLVM (the "language" we use for most of the course) syntax, but they do not always work. I never found a single perfect resource, but when I searched on Google for various versions of LLVM syntax and tried each of them, one of them was likely to work. If not, I had to try to find a workaround. The book is useful for the material we covered in class, but since it's in ML instead of LLVM, it isn't useful for your programs.
What Students Should Know About This Course For Purposes Of Course SelectionIt's a lot of work in the second half of the semester. Annoying work if you have trouble learning LLVM syntax, since it's poorly documented. Professor August prefers to focus on research, but he's still a good lecturer, and his assignments are fair. It's useful to know a small amount about how functions are put on the stack and C++ (or C), but otherwise, 217 and 226 are unnecessary. This course is easily the most useful course I took at Princeton for my future, but it was hard to see that while I was taking it.