ABI를 계속 봐도 잘 이해가 안가서, 다시 공부해보기로 했다.
참고로 해당 내용은 swift github 레포지토리에 docs 내용 중 ABI 관련 내용을 기반으로 공부해보았다.
API가 소스 코드 수준에서의 약속이라면, ABI는 컴파일된 기계어(바이너리) 수준에서의 약속이에요!
ABI의 핵심적인 기둥들을 정리해보자.
Swift는 C나 Objective-C의 규약을 그대로 따르지 않고, Swift 만의 효율적인 방식을 사용해요.
레지스터 활용
self 나 에러 정보 (Error return )를 담기 위한 전용 레지스터를 지정해두어요.소유권 전달 (Ownership)
self 전달 시 주로 사용돼요.)inout 파라미터는 항상 주소값(Address)을 통해 전달돼요.메모리에 데이터가 어떤 순서와 간격으로 배치되는지에 대한 규칙이에요.
Struct & Tuple
nil 처럼 실제로 사용되지 않는 비트 패턴을 활용해 별도의 태그 없이 케이스를 구분하기도 해요.컴파일러는 함수 이름, 타입, 모듈 정보를 하나의 고유한 문자열로 변환해요. 바이너리 내에서 심볼이 충돌하지 않게 하기 위함이죠.
Swift 5+ 안정성
$s 로 시작하는 그 이름들이 그 예입니다.Swift는 런타임에 타입의 정보를 확인하기 위해 모든 타입마다 메타데이터 레코드를 유지해요.
ARM64 아키텍처에서 Swift가 함수를 호출할 때 레지스터를 어떻게 나누어 쓰는지 예시를 보면 ABI의 실체를 더 잘 느낄 수 있어요.
| 레지스터 | Swift에서의 용도 |
|---|---|
x0 | 첫 번째 정수 인자 및 결과값 |
x20 | self (컨텍스트 레지스터) |
x21 | Error 결과값 (에러 발생 시 사용) |
v0-v7 | 부동 소수점 인자들 |