I think LLVM is very readable considering the complexity of what it actually does. It uses C++, but for the most part it uses classes to encapsulate names or as dumb data structures. E.g. an analysis might be implemented as a class, but it'll just be one or two classes with a bunch of non-virtual methods operating on dumb data. The dumb data is encapsulated in objects, but the objects don't really have methods that "know" how to do anything other than manipulate the encapsulated data. All that intelligence is in functions that operate on the data.
It's very different than typical Java code, where an object will "know" how to do non trivial things to itself, and the pieces of an algorithm end up spread over a dozen classes in a dozen different files. Such code will often use elaborate class hierarchies breaking down pieces of an algorithm into objects that interact with virtual method calls, all because of a crippling fear of switch statements. This cuts off the nose to spite the face, rendering the code incomprehensible as a result.
It's very different than typical Java code, where an object will "know" how to do non trivial things to itself, and the pieces of an algorithm end up spread over a dozen classes in a dozen different files. Such code will often use elaborate class hierarchies breaking down pieces of an algorithm into objects that interact with virtual method calls, all because of a crippling fear of switch statements. This cuts off the nose to spite the face, rendering the code incomprehensible as a result.