Global ctor evaluation currently models memory as a map from Constant * to Constant *. For this to be correct, it is required that there is only a single Constant * referencing a given memory location. The Evaluator tries to ensure this by imposing certain limitations that could result in ambiguities (by limiting types, casts and GEP formats), but ultimately still fails, as can be seen in https://github.com/llvm/llvm-bugzilla-archive/issues/51879. The approach is fundamentally fragile and will get more so with opaque pointers.
My original thought was to instead store memory for each global as an offset => value representation. However, we also need to make sure that we can actually rematerialize the modified global initializer into a Constant in the end, which may not be possible if we allow arbitrary writes.
What this patch does instead is to represent globals as a MutableValue, which is either a Constant * or a MutableAggregate *. The mutable aggregate exists to allow efficient mutation of individual aggregate elements, as mutating an element on a Constant would require interning a new constant. When a write to the Constant * is made, it is converted into a MutableAggregate * as needed.
I believe this should make the evaluator more robust, compatible with opaque pointers, and a bit simpler as well.
clang-format: please reformat the code