Add support for ?, DUP, and string initializers, as well as MASM syntax for named data locations.
We could optimize the case of 1000000 dup (2) with a fill-type instruction, but I'm not sure how we would handle (e.g.) 500000 dup (2,3). Also, this is data-initialization logic, so either way the actual binary is going to contain 1M literal copies. Do you think it's worth special-casing the single-value handling internally anyway?
Just a note for the future. Currently this means we actually make 1M copies of the APInt representing a real with value 2 in memory while compiling, and don't let go until we've processed the entire initializer list.
There are three cases here:
Case 1 could be optimized by using Fill logic.
Case 3 is more of a problem, though. Arbitrarily nested duplications get hard unless you expand them in place, as the current code does... or unless you parse them into a specialized tree structure, and expand it back to actual values only as needed.
All of this is complicated by the fact that once STRUCT support is in place, we do need to be able to parse initializers and hold them in memory, not just emit them immediately.
The ideal solution would probably be a tree-based intermediate representation for initializers, with duplication nodes representing "X DUP (<child>)". It's probably worth coming back to this eventually, but we'll leave it as-is for now.