SIL 맛보기

2026. 7. 17. 13:09·iOS/SwiftUI
반응형

👋 들어가기 전

이번 시간은 컴파일 과정과 그 과정중에 있는 SIL에 대해 한번 알아보자.


🏁 학습할 내용

  • 컴파일 과정
    • 컴파일 과정 중, SIL의 역할
  • 간단한 SIL 해석하기

⚙️ 컴파일 과정

 

🌳 AST (Abstract Syntax Tree, 추상 구문 트리) 단계


컴파일의 첫 시작은 소스 코드를 컴퓨터가 분석하기 좋은 구조로 바꾸는 것

  • 구문 분석 (Parsing)
    • Swift 소스 코드(.swift)를 읽어 들여 문법 구조를 트리 형태로 만듬.
    • 이 단계에서는 문법이 맞는지(괄호가 잘 닫혔는지 등)만 확인
  • 의미 분석 및 타입 체킹 (Semantic Analysis & Type Checking):
    • 컴파일러가 AST를 훑으며 타입을 추론하고 검사 (예: String 변수에 Int를 대입하려고 하면 여기서 에러 감지.)
    • 이 과정이 끝나면 모든 타입 정보가 명확하게 기록된 Type-checked AST가 완성
💡AST의 한계

AST는 소스 코드의 구조를 고스란히 담고 있어서 사람이 이해하기에는 좋지만, 프로그램 내에서
데이터가 어떻게 흐르고 제어 흐름(Control Flow)이 어떻게 바뀌는지 분석하기에는 적합하지 않음.
그래서 Swift는 바로 다음 단계인 SIL을 도입


🦅 SIL (Swift Intermediate Language) 단계

타입 체크가 끝난 AST를 바탕으로 Swift만의 독자적인 중간 표현식인 SIL을 생성
이 단계는 크게 두 가지 세부 과정으로 나뉨


🥩 SILGen (Raw SIL 생성)

  • Type-checked AST를 바탕으로 Raw SIL(원시 SIL)을 생성
  • 이 단계의 SIL은 Swift 언어의 의미론적(Semantic) 정보는 온전히 담고 있지만, 아직 메모리 안전성이 검증되지 않았고 최적화도 적용되지 않은 상태


🧪 SIL 분석 및 최적화 (Canonical SIL 생성)

Raw SIL을 꼼꼼히 분석하여 안전성 검사(Diagnostics)를 수행하고, 완벽하게 검증되면 이를 Canonical SIL(규격화된 SIL)로 변환

  • Definite Initialization (확실한 초기화 검사)
    • 변수나 상수, 프로퍼티가 사용되기 전에 반드시 초기화되었는지 흐름을 추적하여 검사
    • 초기화되지 않은 변수를 쓰려고 하면 여기서 컴파일 에러 방출
  • ARC (Automatic Reference Counting) 최적화
    • 객체의 retain/release 호출 위치를 분석하여 불필요한 참조 카운팅 연산을 과감하게 제거
  • Generics Specialization (제네릭 특수화)
    • 제네릭 코드를 분석하여 런타임 오버헤드를 줄이기 위해 실제 구체적인 타입(예: Int, String)으로 동작하는 최적화된 전용 코드를 생성
  • Devirtualization (탈가상화)
    • dynamic dispatch(동적 테이블 탐색)가 필요 없는 메서드 호출을 static dispatch(직접 호출)로 변경하여 실행 속도 개선

 

🤖 IRGen 및 LLVM 단계

 

SIL 단계에서 Swift 레벨의 안전성과 성능 최적화가 끝나면, 이제 완전히 기계에 가까운 언어로 내려갈 차례

  • IRGen (LLVM IR 생성)
    • Canonical SIL을 LLVM IR이라는 보다 저수준의 가상 어셈블리 언어로 변환
    • 이 단계에 도달하면 Swift라는 언어 고유의 개념(ARC, 제네릭 등)은 사라지고 포인터와 기본 데이터 타입 위주로 재구성
  • LLVM Backend: LLVM 프레임워크가 이 IR을 받아서 target 기기(iOS 기기, Mac 등)의 CPU 아키텍처(ARM, x86 등)에 맞는
    최적화된 최종 기계어(Machine Code)를 뽑아냄

 

⭐️ 한눈 비교

비교 항목 AST (추상 구문 트리) SIL (Swift 중간 언어) LLVM IR (저수준 중간 표현식)
추상화 수준 매우 높음 (Swift 소스에 가까움) 중간 (Swift 개념 + 제어 흐름) 낮음 (어셈블리에 가까움)
핵심 역할 구문 분석 및 타입 검사 Swift 전용 안전성 검사 & 최적화 하드웨어 독립적인 범용 최적화
분석 대상 문법적 구조 데이터 흐름, ARC, 제네릭, 초기화 여부 기계 레벨의 레지스터 할당, 루프 최적화

 


🚀 간단한 SIL 해석하기

 

🔥 해석 전 알아야할 필수 개념

먼저 SIL은 다음 형태 커맨드로 확인할 수 있다.

sil 뱉어라 ~

swiftc -emit-sil XXX.swift

 

SIL을 읽기 위한 3가지 필수 개념

SIL 코드를 보기 전에 아래 3가지 개념만 머릿속에 넣어두면 난해한 문법이 한눈에 이해됨

 

1️⃣ Basic Block (기본 블록, bb0)

  • 정의: 중간에 한눈팔지 않고 처음부터 끝까지 일직선으로만 실행되는 코드의 덩어리
  • 특징
    • 진입점(시작)과 출구(끝)가 오직 하나뿐
    • 모든 SIL 함수는 반드시 bb0으로 시작 (함수의 현관문 역할이자, 매개변수를 넘겨받는 시작점)
    • 조건문(if) 등을 만나 흐름이 갈라지면 bb1, bb2 등 새로운 블록이 생성됨

2️⃣ user: %X 주석 (소비처 표지판)

  • 의미: "현재 라인에서 생성된 임시 레지스터(가상 변수)가 향후 몇 번째 라인(%X)에서 사용(Use)되는지" 컴파일러가 미리 알려주는 정보
  • 중요성: 만약 user가 없는 변수가 있다면, 컴파일러는 "아무도 안 쓰는구나!" 판단하고 코드를 삭제하는 최적화를 수행

3️⃣ id: %Y 주석 (방 번호 표지판)

  • 의미: 이 명령어가 실행되는 현재 라인 자체의 고유한 식별 아이디가 %Y 번이다"라는 것을 뜻

 

🧐 분석

 

아래 함수의 SIL을 분석해보겠음 , Swift코드는 짧은데 SIL이 엄청김
컴파일러 과정에서 생각보다 힘내고 있구나 반성하게됨

 

func add(n1 a: Int, n2 b: Int) -> Int {
    return a + b
}

 

일단 전체 코드는 다음과 같고 섹션 별로 하나씩 살펴보자.

 

👀 import 및 프로토 타입 정의

sil_stage canonical

import Builtin
import Swift
import SwiftShims

func add(n1 a: Int, n2 b: Int) -> Int
  • sil_stage canonical
    • 현재 Canonical 단계,  1차적인 분석과 최적화를 모두 마친 기계어에 가까운 상태의 SI
  • import Builtin
    • Swift언어 내부에서만 사용하는 원시적인 타입
  • import Swift
    • 우리가 아는 Swift 표준 라이브러리
  • import SwiftShims
    • Swift와 C 시스템 라이브러리 간의 단리 역할을 하는 내부 헤더들
  • func add(n1 a: Int, n2 b: Int) -> Int
    • Swift 소스 코드에 정의되어 있는 함수 시그니처(c언어의 프로토타입)

 

🏛️ add 함수 

// add(n1:n2:)
sil hidden @$s8Contents3add2n12n2S2i_SitF : $@convention(thin) (Int, Int) -> Int {
// %0 "a"                                         // users: %4, %2
// %1 "b"                                         // users: %5, %3
bb0(%0 : $Int, %1 : $Int):
  debug_value %0, let, name "a", argno 1          // id: %2
  debug_value %1, let, name "b", argno 2          // id: %3
  %4 = struct_extract %0, #Int._value             // user: %7
  %5 = struct_extract %1, #Int._value             // user: %7
  %6 = integer_literal $Builtin.Int1, -1          // user: %7
  %7 = builtin "sadd_with_overflow_Int64"(%4, %5, %6) : $(Builtin.Int64, Builtin.Int1) // users: %9, %8
  %8 = tuple_extract %7, 0                        // user: %11
  %9 = tuple_extract %7, 1                        // user: %10
  cond_fail %9, "arithmetic overflow"             // id: %10
  %11 = struct $Int (%8)                          // user: %12
  return %11                                      // id: %12
} // end sil function '$s8Contents3add2n12n2S2i_SitF'

 

🔵 함수 선언부

sil hidden @$s8Contents3add2n12n2S2i_SitF : $@convention(thin) (Int, Int) -> Int {
  • @$s8Contents3...
    • 컴파일러가 함수 이름을 고유하게 변환한 네임 맹글링(Name Mangling)된 심볼
  • hidden
    • internal 접근 제어 수준을 가집니다.
  • @convention(thin)
    • 클로저처럼 힙 메모리 참조가 필요 없는 순수하고 가벼운 함수임을 명시합니다.

 

🔵 함수 진입 및 매개변수 바인딩

// %0 "a"                                         // users: %4, %2
// %1 "b"                                         // users: %5, %3
bb0(%0 : $Int, %1 : $Int):
  • 함수의 시작점인 bb0 열리며, 입력받은 인자 2개를 각각 임시레지스터 %0(변수 a)와 %1(변수 b)에 대입
  • %0은 향후 %4와 %2 라인에서 사용(users)될 예정임을 미리 알려줌

 

🔵 디버깅 정보 매핑

  debug_value %0, let, name "a", argno 1          // id: %2
  debug_value %1, let, name "b", argno 2          // id: %3
  • 개발자가 디버깅할 떄 변수 이름을 알 수 있도록 LLDB 디버거에 메타 데이터 정보를 제공 (%0 = a , %1 = b)
  • 이 라인들의 고유 ID는 각각 %2와 %3이 된다.

 

🔵 구조체 내부 원시 값 추출

  %4 = struct_extract %0, #Int._value             // user: %7
  %5 = struct_extract %1, #Int._value             // user: %7
  • Swift의 Int는 사실 내부적으로 64비트 정수를 품고 있는 구조체
  • 실제 물리 연산을 하기 위해 구조체 속 알맹이 값인 #Int._value를 꺼내서 각각 %4와 %5에 저장
  • 둘 다 연산을 위해 %7라인에서 사용됨

 

🔵 오버플로우 활성화 및 덧셈 연산

  %6 = integer_literal $Builtin.Int1, -1          // user: %7
  %7 = builtin "sadd_with_overflow_Int64"(%4, %5, %6) : $(Builtin.Int64, Builtin.Int1) // users: %9, %8

 

  • sadd_with_overflow_Int64
    • Swift의 안전한 연산을 담당하는 핵심 핵심 내장 함수. 추출한 두 정수(%4, %5)를 더하되, 세 번째 인자(%6 = true)를 통해
      오버플로우를 감지
  • %6에 1비트짜리 불리언 값인 true(-1)를 저장
  • 연산 결과물로 (실제 더해진 값, 오버플로우 여부) 쌍을 가진 튜플이 생성되어 %7에 저장

 

🔵 오버플로우 검사

  %8 = tuple_extract %7, 0                        // user: %11
  %9 = tuple_extract %7, 1                        // user: %10
  cond_fail %9, "arithmetic overflow"             // id: %10
  • %8: 튜플에서 실제 더해진 결과값을 추출
  • %9: 튜플에서 오버플로우가 났는지 여부(true/false)를 추출
  • cond_fail %9
    • 만약 오버플로우 값인 %9가 true라면 프로그램을 즉시 중단(Crash)시키며 "arithmetic overflow" 에러 방출

 

🔵 구조체 재포장 및 반환

  %11 = struct $Int (%8)                          // user: %12
  return %11                                      // id: %12
  • 오버플로우 검사를 무사히 통과했다면, 안전한 정수 결과물인 %8을 다시 Swift 표준 Int 구조체로 래핑
  • 최종 포장된 값 %11을 반환하며 함수 완전종료

 


출처

반응형

'iOS > SwiftUI' 카테고리의 다른 글

photoPicker에서 AVAsset 추출하기  (0) 2026.02.16
onScrollGeometryChange  (0) 2026.02.09
[WWDC2024] Create custom visual effects with SwiftUI  (0) 2025.11.19
PhotoPicker  (0) 2025.11.02
[WWDC 2023] Wind your way through advanced animations in SwiftUI  (0) 2025.10.30
'iOS/SwiftUI' 카테고리의 다른 글
  • photoPicker에서 AVAsset 추출하기
  • onScrollGeometryChange
  • [WWDC2024] Create custom visual effects with SwiftUI
  • PhotoPicker
Hamp
Hamp
남들에게 보여주기 부끄러운 잡다한 글을 적어 나가는 자칭 기술 블로그입니다.
  • Hamp
    Hamp의 분리수거함
    Hamp
  • 전체
    오늘
    어제
    • 분류 전체보기 (344) N
      • CS (30)
        • 객체지향 (2)
        • Network (7)
        • OS (6)
        • 자료구조 (1)
        • LiveStreaming (3)
        • 이미지 (1)
        • 잡다한 질문 정리 (0)
        • Hardware (2)
        • 이론 (6)
        • 컴퓨터 그래픽스 (0)
      • Firebase (3)
      • Programing Langauge (44) N
        • swift (37) N
        • python (6)
        • Kotlin (1)
      • iOS (136)
        • UIKit (37)
        • Combine (1)
        • SwiftUI (35)
        • Framework (7)
        • Swift Concurrency (22)
        • Tuist (6)
        • Setting (11)
        • Modularization (2)
        • Instruments (6)
      • PS (59)
        • 프로그래머스 (24)
        • 백준 (13)
        • LeetCode (19)
        • 알고리즘 (3)
      • Git (18)
        • 명령어 (4)
        • 이론 (2)
        • hooks (1)
        • config (2)
        • action (7)
      • Shell Script (2)
      • Linux (6)
        • 명령어 (5)
      • Spring (21)
        • 어노테이션 (6)
        • 튜토리얼 (14)
      • CI-CD (4)
      • Android (0)
        • Jetpack Compose (0)
      • AI (21)
        • 이론 (10)
        • MCP (1)
        • LangGraph (10)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    프로그래머스
    백준
    IOS
    dispatch
    AVFoundation
    concurrency
    protocol
    dp
    투포인터
    dfs
    GIT
    CS
    UIKit
    Tuist
    boostcamp
    Spring
    lifecycle
    SwiftUI
    Swift
    property
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.0
Hamp
SIL 맛보기
상단으로

티스토리툴바