Comdat
public class Comdat
A Comdat
object represents a particular COMDAT section in a final
generated ELF or COFF object file. All COMDAT sections are keyed by a
unique name that the linker uses, in conjunction with the section’s
selectionKind
to determine how to treat conflicting or identical COMDAT
sections at link time.
COMDAT sections are typically used by languages where multiple translation
units may define the same symbol, but where
“One-Definition-Rule” (ODR)-like concepts apply (perhaps because taking the
address of the object referenced by the symbol is defined behavior). For
example, a C++ header file may define an inline function that cannot be
successfully inlined at all call sites. The C++ compiler would then emit
a COMDAT section in each object file for the function with the .any
selection kind and the linker would pick any section it desires before
emitting the final object file.
It is important to be aware of the selection kind of a COMDAT section as
these provide strengths and weaknesses at compile-time and link-time. It
is also important to be aware that only certain platforms support mixing
identically-keyed COMDAT sections with mixed selection kinds e.g. COFF
supports mixing .any
and .largest
, WebAssembly only supports .any
,
and Mach-O doesn’t support COMDAT sections at all.
When targeting COFF, there are also restrictions on the way global objects must appear in COMDAT sections. All global objects and aliases to those global objects must belong to a COMDAT group with the same name and must have greater than local linkage. Else the local symbol may be renamed in the event of a collision, defeating code-size savings.
The combined use of COMDATS and sections may yield surprising results. For example:
let module = Module(name: "COMDATTest")
let builder = IRBuilder(module: module)
let foo = module.comdat(named: "foo")
let bar = module.comdat(named: "bar")
var g1 = builder.addGlobal("g1", initializer: IntType.int8.constant(42))
g1.comdat = foo
var g2 = builder.addGlobal("g2", initializer: IntType.int8.constant(42))
g2.comdat = bar
From the object file perspective, this requires the creation of two sections with the same name. This is necessary because both globals belong to different COMDAT groups and COMDATs, at the object file level, are represented by sections.
-
The selection kind for this COMDAT section.
Declaration
Swift
public var selectionKind: Comdat.SelectionKind { get set }
-
A
See moreComdat.SelectionKind
describes the behavior of the linker when linking COMDAT sections.Declaration
Swift
public enum SelectionKind