Commits

Slava Pestov committed 65a5a03f268
IRGen: Add a new destructiveInjectEnumTag value witness function This value witness function takes an address of an enum value where the payload has already been initialized, together with a case index, and forms the enum value. The formal behavior can be thought of as satisfying an identity in relation to the existing two enum value witnesses. For any enum value, the following is to leave the value unchanged: tag = getEnumTag(value) destructiveProjectEnumData(value) destructiveInjectEnumData(value, tag) This is the last missing piece for the inject_enum_addr SIL instruction to handle resilient enums, allowing the implementation of an enum to be decoupled from its uses. Also, it should be useful for dynamically constructing enum cases with write reflection, once we get around to doing such a thing. The body of the value witness is emitted by a new emitStoreTag() method on EnumImplStrategy. This is similar to the existing storeTag(), except the case index is a value instead of a contant. This is implemented as follows for the different enum strategies: 1) For enums consisting of a single case, this is trivial. 2) For enums where all cases are empty, stores the case index into the payload area. 3) For enums with a single payload case, emits a call to a runtime function. Note that for non-generic single payload enums, this could be open-coded more efficiently, but the function still has the correct behavior since it supports extra inhabitants and so on. A follow-up patch will make this more efficient. 4) For multi-payload enums, there are two cases: a) If one of the payloads is generic or resilient, the enum is dynamically-sized, and a call to a runtime function is emitted. b) If the entire enum is fixed-size, the value witness checks if the case is empty or not. If the case has a payload, the case index is swizzled into spare bits of the payload, if any, with remaining bits going into the extra tag area. If the case is empty, the case index is swizzled into the spare bits of the payload, the remaining bits of the payload, and the extra tag area. The implementations of emitStoreTag() duplicate existing logic in the enum strategies, in particular case 4)b) is rather complicated. Code cleanups are welcome here!