SE-0492: Section Placement Control

One of the big reasons that Clang/GCC don't suffer from just having __attribute__((__section__("..."))) is because people writing a multi-platform library are pretty much always going to hide that attribute in a preprocessor macro. The section names would rarely appear as literal strings at the usage site; they'd define a custom macro per "thing" and it would just expand to the right section name based on target environment.

It would be nice if we could define a custom macro like this that would expand to the right conditionals:

@MyCustomSection func foo() {}

But that's not possible with today's attached macros AFAIK; macros can only apply attributes to a type's members (and even those can only be AttributeSyntax nodes, which I believe forbids injecting attributes that need to be surrounded by #if). Even if it were possible, asking a library to write a macro just to do this substitution is a pretty large undertaking.

I think the future direction of allowing a compile-time-constant string to be used for the section name is the most scalable choice going forward. That would let a library author define once the target-specific names for whatever sections they need, and then at all the usage sites they would only need to write @section(whateverTheVariableIsNamed).

On the other hand, the suggested alternative of @section(elf: ..., macho:, ..., ...) wouldn't permit that simplification. Even if the individual section names were defined as compile-time constants, all of them would still need to be repeated.

If we look at them side-by-side, first with the singular attribute:

#if objectFileFormat(MachO)
/*constant initialized*/ let mySection = "__DATA,mySection"
#elseif objectFileFormat(ELF)
/*constant initialized*/ let mySection = "something_else"
#elseif objectFileFormat(COFF)
/*constant initialized*/ let mySection = "i_dont_know_windows"
#endif

@section(mySection)
func someFunction() {}

@section(mySection)
func someOtherFunction() {}

And now with a version of the attribute that takes the object formats inline:

/*constant initialized*/ let mySectionMachO = "__DATA,mySection"
/*constant initialized*/ let mySectionELF = "something_else"
/*constant initialized*/ let mySectionCOFF = "i_dont_know_windows"
#endif

@section(macho: mySectionMachO, elf: mySectionELF, coff: mySectionCOFF)
func someFunction() {}

@section(macho: mySectionMachO, elf: mySectionELF, coff: mySectionCOFF)
func someOtherFunction() {}

I think the first one is the clear winner in clarity. So even though we have to pay the cost of more repetition in the short term, in the long term the singular @section("...") scales far better. I think we would end up regretting a version of @section that has to keep chasing after various configurations with an ad hoc syntax vs. one that composes more simply using the right conditionals.

4 Likes