ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SE-0537] Section Placement Control for Functions
    Swift 2026. 8. 15. 07:20

    안녕하세요. 그린입니다 🍏
    이번 포스팅에서는 SE-0537 — 함수를 위한 섹션 배치 제어에 대해 정리해보겠습니다 🙋🏻

    Intro

    Proposal: SE-0537

    Author: Doug Gregor

    Review Manager: Becca Royal-Gordon

    Status: Accepted

    Implementation: swiftlang/swift#89740

    SE-0492에서 도입된 @section 어트리뷰트를 함수에도 붙일 수 있도록 확장하는 제안이에요.

    임베디드 시스템에서 펌웨어 부팅 코드처럼 바이너리의 특정 섹션에 들어가야 하는 코드가 있을 때 유용합니다.

     

    Motivation

    @section 어트리뷰트는 특정 엔티티가 오브젝트 파일의 어느 섹션에 배치될지 지정해요.

    특히 임베디드 환경에서는 링커나 다른 도구들이 특정 종류의 심볼이 특정 섹션에 있길 기대하는 경우가 많죠.

    SE-0492는 전역/static 변수에 대한 @section 지원을 도입했지만, 함수는 future direction으로 남겨뒀어요.

     

    하지만 함수에도 이 지원이 필요합니다.

     

    대표적인 사례가 펌웨어 진입점이나 부팅 스킴인데, startup 코드가 미리 정의된 섹션에 있어야 하는 경우가 많거든요.

    // 이 함수의 코드는 커스텀 섹션에 배치됩니다
    @section("__TEXT,boot")
    func firmwareBootEntrypoint() { ... }

    이건 SE-0492의 Future Directions에서도 이미 언급됐던 내용이에요.

     

    Proposed Solution

    일반 함수(func), 이니셜라이저(init), deinitializer(deinit), 클로저, accessor(get, set 등)를 포함한 모든 종류의 함수에 @section 어트리뷰트를 쓸 수 있게 합니다.

    그리고 어떤 추론 규칙이든 무시하고 플랫폼 기본 섹션을 적용하는 @section(default) 표기법도 함께 도입해요.

     

    Detailed Design

    @section 어트리뷰트는 어떤 종류의 함수에도 적용할 수 있어요.

     

    문법을 보여주는 몇 가지 예시입니다.

    @section("__TEXT,boot")
    func firmwareBootEntrypoint() { ... }
    
    struct MyBootConfig: ~Copyable {
      @section("__TEXT,boot") init() { 
        registerCallback { @section("__TEXT,boot") in 
          ...
        }
      }
    
      @section("__TEXT,boot") deinit { }
    
      var bootPhase: Int {
        @section("__TEXT,boot") get { ... }
        @section("__TEXT,boot") set { ... } 
      }
    }

     

    변수에 붙이는 @section과 달리, 제네릭 함수나 제네릭 컨텍스트 안의 함수에 쓰는 데는 아무런 제약이 없어요.

    모든 함수는 결국 text 섹션에 들어가기 때문이에요.

    그래서 @section은 타입의 인스턴스 함수에도 적용할 수 있습니다.

     

    @section 어트리뷰트는 그 함수뿐 아니라 구현이 함께 만들어내는 관련 함수들에도 적용돼요.

    예를 들어 async 함수에 붙이면, 구현이 생성하는 각각의 partial function들도 이 @section을 따릅니다.

    마찬가지로 제네릭 함수에 @section을 붙이면, 컴파일러가 만들어내는 그 제네릭 함수의 모든 specialization에도, 그리고 원본 제네릭 정의에도 적용돼요.

     

    마지막으로 @main 타입의 main 함수에 @section이 있으면, 컴파일러가 만들어내는 실제 main 진입점에도 같은 섹션이 쓰입니다.

     

    accessor, closure, 지역 함수에서의 @section 추론

    accessor나 closure에 @section을 명시하지 않으면 다음 규칙으로 추론될 수 있어요.

    클로저나 지역 함수는 (있다면) 감싸고 있는 함수로부터 @section을 추론합니다.

    @section("__TEXT,boot")
    func firmwareBootEntrypoint() {
      func helper() { // @section("__TEXT,boot") 추론됨
    
      }
    
      registerCallback { // @section("__TEXT,boot") 추론됨
        ...
      }
    }

     

    구현이 합성하는 읽기 전용 접근자(get, borrow, yielding borrow 등)는, 명시적으로 작성된 다른 접근자로부터 @section을 추론합니다.

     

    구현이 합성하는 읽기/쓰기 또는 쓰기 접근자(set, mutate, yielding mutate, init, didSet, willSet)도, 명시적으로 작성된 다른 접근자로부터 @section을 추론합니다.

     

    예를 들면 이렇게요.

      var scratchSpace: MutableSpan {
        @section("__TEXT,boot") borrow { ... }
        // 합성된 "get"이 'borrow'로부터 @section("__TEXT,boot")를 추론함
        
        @section("__TEXT,boot") mutate { ... }
        // 합성된 "set"이 'mutate'로부터 @section("__TEXT,boot")를 추론함 
      }

    변수에서 그 accessor로는 @section이 추론되지 않아요.

    코드와 데이터는 보통 서로 다른 섹션에 들어가기 때문이에요.

    local 타입(과 그 멤버)도 섹션이 추론되지 않습니다.

     

    @section 추론 억제하기

    default 키워드를 섹션 값으로 쓰면, 이 선언에는 플랫폼에 맞는 기본 섹션을 쓰라는 뜻이 돼요.

    그러면 원래 적용됐을 추론 규칙을 모두 무시합니다.

    @section("__TEXT,boot")
    func firmwareBootEntrypoint() {
      @section(default) func helper() { // @section("__TEXT,boot") 추론을 억제함
    
      }
    }

     

    didSet/willSet 제약 완화

    SE-0492는 @section이 붙은 변수에 다음 제약을 뒀었어요.

     

    그 변수는 프로퍼티 옵저버(didSet, willSet)를 가질 수 없다.

     

    이 제약은 불필요한 것으로 판단되어 이번 제안에서 없앱니다.

    didSet이나 willSet에도 @section을 붙일 수 있고, 이 값은 구현이 실제로 합성하는 접근자(예: set)에 대한 추론에 쓰입니다.

     

    Future Directions

    데이터와 함수 섹션 어트리뷰트 분리하기

    Swift의 일부 선언은 데이터 심볼과 함수 심볼을 동시에 내보내요.

    예를 들어 타입을 정의할 때 메타데이터 심볼(데이터)과 메타데이터 접근자 함수(함수)가 함께 생길 수 있죠.

    이 제안도 SE-0492도 타입 정의에 @section을 허용하진 않지만, 만약 허용한다면 데이터용과 함수용 섹션을 따로 표현할 방법이 필요할 거예요.

     

    예를 들면 이런 모습일 수 있습니다.

    @section(data: "__DATA,mysection")
    @section(function: "__FUNCTION,mysection")
    public struct MyStruct { ... }

     

    datafunction도 지정하지 않은 @section은, 이 제안과 SE-0492가 다루는 것처럼 데이터/함수 구분이 모호하지 않은 곳에서만 적용될 거예요.

    타입 정의, extension, 프로토콜 conformance, 파일 단위 기본값처럼 데이터와 함수 심볼을 동시에 내보내는 새로운 자리들이 이 새 문법을 쓸 수 있게 될 겁니다.

     

    이 제안이 승인되는 과정에서, 추론을 억제하고 기본 섹션을 지정하는 @section(default) 기능이 새로 도입됐어요.

     

    Conclusion

    변수에만 적용되던 @section이 이제 func, init, deinit, 클로저, accessor까지 아우르게 됐어요 😁

    특히 감싸는 함수로부터 @section이 자동으로 추론되는 규칙 덕분에, 펌웨어 부팅 코드처럼 특정 섹션에 몰아넣어야 하는 코드 전체를 일일이 어트리뷰트로 도배하지 않아도 될 것 같아요.

    임베디드 환경에서 Swift를 쓰는 개발자들에게 꽤 실용적인 도구가 하나 더 생긴 셈입니다 🙌

     

    References

     

    swift-evolution/proposals/0537-function-sections.md at main · swiftlang/swift-evolution

    This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution

    github.com

Designed by Tistory.