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 Comdat.SelectionKind describes the behavior of the linker when linking COMDAT sections.

    See more

    Declaration

    Swift

    public enum SelectionKind