Fundamentals 19 min read

Exploring Swift Enum Implementation: SIL, Memory Layout, Raw Values, Associated Values, and Protocols

This article delves into the inner workings of Swift enums—covering their compilation to SIL, memory representation, use of MemoryLayout for size and alignment, techniques for retrieving variable addresses, the role of raw values and associated values, and how default protocols like Equatable and Hashable are automatically provided.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Exploring Swift Enum Implementation: SIL, Memory Layout, Raw Values, Associated Values, and Protocols

After Swift 5.0 stabilized the ABI, developers increasingly adopt Swift for its concise syntax and safety features. To truly master the language, one must understand not only how to use enums but also how they are implemented under the hood.

SIL (Swift Intermediate Language) sits between Swift source code and LLVM IR. Like Objective‑C, Swift code is first compiled by the Swift front‑end into SIL, optimized, and then emitted as LLVM IR before becoming machine code.

The memory layout of a Swift program consists of stack, heap, global, constant, and code sections. By inspecting memory directly, we can reveal how enums store data.

Swift provides MemoryLayout.size(ofValue:) , MemoryLayout.stride(ofValue:) and MemoryLayout.alignment(ofValue:) to query a variable’s size, aligned size, and alignment. For example, an Int occupies 8 bytes on a 64‑bit system, while a simple enum Color { case red, yellow, blue } occupies just 1 byte.

To obtain a variable’s address, we can define a helper:

func getPointer
(of value: inout T) -> UnsafeRawPointer {
    return withUnsafePointer(to: &value) { UnsafeRawPointer($0) }
}

Using this function together with Xcode’s memory view or the memory read command in LLDB allows us to inspect the raw byte stored for an enum case (e.g., Color.blue stores 0x2 ).

When an enum has a raw value, Swift synthesizes a rawValue computed property and an initializer via the RawRepresentable protocol, without changing the enum’s memory footprint.

Enums with associated values store both the case discriminator and the associated payload. The size of such an enum equals the size of the largest associated value plus the discriminator byte (e.g., enum Color { case red(val: Int); case yellow(val: Bool); case blue } occupies 9 bytes).

Instance methods, static methods, and computed properties on enums are compiled into regular functions that take the enum (or its type) as the first parameter. SIL shows apply instructions calling these functions.

For simple enums without associated values, the compiler automatically conforms them to Equatable and Hashable . Once associated values are added, the compiler cannot synthesize these conformances because it cannot know how to compare or hash the heterogeneous payloads.

Overall, the article demonstrates how Swift enums are represented in memory, how to probe them with SIL and runtime APIs, and why certain language features (raw values, associated values, protocol conformances) behave the way they do.

ProgrammingenumSwiftmemory layoutSILAssociated ValueRawValue
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.