<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-01-19" />
  <title>Modules ABI Requirement</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span. { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
font-size: 135%;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
  
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Modules ABI Requirement</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>D3092R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-01-19</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      SG15, ABI Review Group<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Chuanqi Xu<br>&lt;<a href="mailto:chuanqi.xcq@alibaba-inc.com" class="email">chuanqi.xcq@alibaba-inc.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#motivation"><span class="toc-section-number">2</span> Motivation<span></span></a></li>
<li><a href="#simple-introduction-for-modules"><span class="toc-section-number">3</span> Simple introduction for modules<span></span></a></li>
<li><a href="#new-requirement-to-abi"><span class="toc-section-number">4</span> New requirement to ABI<span></span></a>
<ul>
<li><a href="#module-initializers"><span class="toc-section-number">4.1</span> Module Initializers<span></span></a></li>
<li><a href="#module-linkage"><span class="toc-section-number">4.2</span> Module Linkage<span></span></a></li>
</ul></li>
<li><a href="#abi-related-change-in-the-language-side"><span class="toc-section-number">5</span> ABI related change in the language side<span></span></a>
<ul>
<li><a href="#tu-locals"><span class="toc-section-number">5.1</span> TU-locals<span></span></a></li>
<li><a href="#in-class-member-functions-is-not-implicitly-inline-in-modules-purview"><span class="toc-section-number">5.2</span> in-class member functions is not implicitly inline in modules purview<span></span></a></li>
</ul></li>
<li><a href="#std-modules"><span class="toc-section-number">6</span> Std modules<span></span></a></li>
<li><a href="#wishes"><span class="toc-section-number">7</span> Wishes<span></span></a>
<ul>
<li><a href="#abi-boundaries"><span class="toc-section-number">7.1</span> ABI boundaries<span></span></a></li>
</ul></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>C++20 introduces a new language construct <code class="sourceCode default">Modules</code>. <code class="sourceCode default">Modules</code> has non-trivial implications for ABIs. Although we tried to not break previous ABI specification and we made it, it is still helpful to describe the requirement to ABI for modules precisely so that the ABI specication can understand what is allowed to change and what is not allowed.</p>
<h1 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>The motivation of the paper is a discussion about how to define virtual tables in modules: https://github.com/itanium-cxx-abi/cxx-abi/issues/170.</p>
<p>Prior to modules, the virtual table is emitted in the same object containing the definition of its key function, i.e. the first non-pure virtual function that is not inline at the point of class definition.</p>
<p>The rule can work well even after modules come in. However, the ABI can get rid of the concept of key functions within modules. It can simplify the mental model and the implementations.</p>
<p>This is a good example why this document is needed. While we introduce a new language construct and the old ABI rules could work well, the ABI rules can get improved for modules after they understand new construct well.</p>
<h1 data-number="3" id="simple-introduction-for-modules"><span class="header-section-number">3</span> Simple introduction for modules<a href="#simple-introduction-for-modules" class="self-link"></a></h1>
<p>Modules allow us to get informations from other (importable) module units.</p>
<p>e.g.,</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="co">// a.cppm</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">export</span> <span class="kw">module</span> a;</span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="kw">export</span> <span class="dt">int</span> a() { <span class="cf">return</span> <span class="dv">43</span>; }</span>
<span id="cb1-4"><a href="#cb1-4"></a></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="co">// b.cpp</span></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="kw">import</span> a;</span>
<span id="cb1-7"><a href="#cb1-7"></a><span class="dt">int</span> b() { <span class="cf">return</span> a(); }</span></code></pre></div>
<p>(In <code class="sourceCode default">b.cpp</code>, we can call function <code class="sourceCode default">a</code> without declaring it earlier in the current TU.)</p>
<p>Module units are new translation unit kinds, including:</p>
<ul>
<li>Primary module interface unit. A translation unit containing a module declaration <code class="sourceCode default">export module &lt;module-name&gt;;</code>. <code class="sourceCode default">&lt;module-name&gt;</code> should be in the form of <code class="sourceCode default">[a-zA-Z_][a-zA-Z_0-9\.]*</code>. In a valid program, there shouldn’t be multiple primary module interface units with the same <code class="sourceCode default">&lt;module-name&gt;</code>.</li>
<li>Module implementation unit. A translation unit containing a module declaration <code class="sourceCode default">module &lt;module-name&gt;;</code>. There can be multiple module implementation units with the same <code class="sourceCode default">&lt;module-name&gt;</code>. The module implementation units will import the corresponding primary module interface unit implicitly.</li>
<li>Module interface partition unit. A translation unit containing a module declaration <code class="sourceCode default">export module &lt;module-name&gt;:&lt;partition-name&gt;;</code>. <code class="sourceCode default">&lt;partition-name&gt;</code> has the same form with <code class="sourceCode default">&lt;module-name&gt;</code>. In a valid program, there shouldn’t be multiple module partition units with the same <code class="sourceCode default">&lt;module-name&gt;:&lt;partition-name&gt;</code> pair. All the module interface partition unit should directly or indirectly be exported by the corresponding primary module interface unit.</li>
<li>Module internal module partition unit. A translation unit containing a module declaration <code class="sourceCode default">module &lt;module-name&gt;:&lt;partition-name&gt;;</code></li>
</ul>
<p>Every module unit should have exactly one module declaration.</p>
<p>Each module unit consists of the following form:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb1-1"><a href="#cb1-1"></a>[&lt;global-module-fragment&gt;]</span>
<span id="cb1-2"><a href="#cb1-2"></a>&lt;module-declaration&gt;</span>
<span id="cb1-3"><a href="#cb1-3"></a>...</span>
<span id="cb1-4"><a href="#cb1-4"></a>[module :private;] // optional</span></code></pre></div>
<p>A global module fragment is an optional section in the following form:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb2-1"><a href="#cb2-1"></a>module;</span>
<span id="cb2-2"><a href="#cb2-2"></a>...</span></code></pre></div>
<p>The global module is the collection of all global-module-fragments and all translation units that are not module units. Declarations appearing in such a context are said to be in the purview of the global module.</p>
<p>The section from <code class="sourceCode default">&lt;module-declaration&gt;</code> to the end of the module unit is called module unit purview. The purview of a named module <code class="sourceCode default">M</code> is the set of module unit purviews of <code class="sourceCode default">M</code>’s module units.</p>
<p>Every declaration are either attached to the global module or a named module. The rules are described here <a href="https://eel.is/c++draft/module.unit#7">module.unit/p7</a>:</p>
<ul>
<li>If the declaration is a non-dependent friend declaration that nominates a function with a declarator-id that is a qualified-id or template-id or that nominates a class other than with an elaborated-type-specifier with neither a nested-name-specifier nor a simple-template-id, it is attached to the module to which the friend is attached.</li>
<li>Otherwise, the declaration is attached to the global module if
<ul>
<li>is a namespace-definition with external linkage or</li>
<li>appears within a linkage-specification</li>
</ul></li>
<li>Otherwise, the declaration is attached to the module in whose purview it appears.</li>
</ul>
<p>The section under <code class="sourceCode default">module :private;</code> is called private module fragment. The private module fragment can only appear in a primary module interface unit. And a primary module interface unit containing a private module fragment should be the only module unit of the corresponding module. The entities in private module fragment won’t affect other translation units. We can think the entities in private module fragment as if they are in an seperate module implementation unit.</p>
<p>The module purviews of module units with same <code class="sourceCode default">&lt;module-name&gt;</code> consist a module with <code class="sourceCode default">&lt;module-name&gt;</code>.</p>
<p>The primary module interface unit, module interface partition unit and module internal partition unit are called importable module unit.</p>
<p>The importable module unit should be compiled into object files and BMI (Built Module Interface) files. The format of BMI files is implementation defined.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb3-1"><a href="#cb3-1"></a>                     +---------- object files</span>
<span id="cb3-2"><a href="#cb3-2"></a>                     |</span>
<span id="cb3-3"><a href="#cb3-3"></a>importable units ----&#39;</span>
<span id="cb3-4"><a href="#cb3-4"></a>                     |</span>
<span id="cb3-5"><a href="#cb3-5"></a>                     +---------- BMI files</span></code></pre></div>
<h1 data-number="4" id="new-requirement-to-abi"><span class="header-section-number">4</span> New requirement to ABI<a href="#new-requirement-to-abi" class="self-link"></a></h1>
<p>This section describes the requirement of modules to ABI specification.</p>
<p>There is already an implementation in clang and GCC and there is pull request to add this to Itanium C++ ABI: https://github.com/itanium-cxx-abi/cxx-abi/pull/144</p>
<h2 data-number="4.1" id="module-initializers"><span class="header-section-number">4.1</span> Module Initializers<a href="#module-initializers" class="self-link"></a></h2>
<p>All the importable module units are required to emit an initializer function. The initializer function should contain calls to importing modules first and all the dynamic-initializers in the current module unit then.</p>
<p>Translation units explicitly or implicitly importing named modules must call the initializer functions of the imported named modules within the sequence of the dynamic-initializers in the TU. Initializations of entities at namespace scope are appearance-ordered. This (recursively) extends into imported modules at the point of appearance of the import declaration.</p>
<p>It is allowed to omit calls to importing modules if it is known empty.</p>
<p>It is allowed to omit calls to importing modules for which is known to be called.</p>
<h2 data-number="4.2" id="module-linkage"><span class="header-section-number">4.2</span> Module Linkage<a href="#module-linkage" class="self-link"></a></h2>
<p>The language specification introduces a new linkage <code class="sourceCode default">module linkage</code>.</p>
<p>All non <code class="sourceCode default">TU-local</code> (See below) entities attached to the purview of named mdoules, which don’t get external linkage by other means, has <code class="sourceCode default">module linkage</code>. When a name has module linkage, the entity it denotes can be referred to by names from other scopes of the same module unit or from scopes of other module units of that same module.</p>
<p>(Note: ‘Inline’ doesn’t change attachment and therefore doesn’t affect linkage in this respect.)</p>
<p>In clang and GCC, we implement <code class="sourceCode default">module linkage</code> by introducing new mangle names. See https://github.com/itanium-cxx-abi/cxx-abi/pull/144 for details.</p>
<h1 data-number="5" id="abi-related-change-in-the-language-side"><span class="header-section-number">5</span> ABI related change in the language side<a href="#abi-related-change-in-the-language-side" class="self-link"></a></h1>
<p>This section describes the change in the language side but not requiring the ABI spec to change.</p>
<h2 data-number="5.1" id="tu-locals"><span class="header-section-number">5.1</span> TU-locals<a href="#tu-locals" class="self-link"></a></h2>
<p>Module units are translation units that can be imported. Then we should avoid the internal linkage get imported into other translation units.</p>
<p>To address the idea, we bring the concept of <code class="sourceCode default">TU-locals</code> and <code class="sourceCode default">exposure</code> to the language. The formal definitions to <code class="sourceCode default">TU-locals</code> and <code class="sourceCode default">exposure</code> are <a href="%5Bhttps://eel.is/c++draft/basic.link#14%5D">basic.link/p14</a>, <a href="%5Bhttps://eel.is/c++draft/basic.link#15%5D">basic.link/p15</a>, <a href="%5Bhttps://eel.is/c++draft/basic.link#16%5D">basic.link/p16</a>, <a href="%5Bhttps://eel.is/c++draft/basic.link#17%5D">basic.link/p17</a> and <a href="%5Bhttps://eel.is/c++draft/basic.link#18%5D">basic.link/p18</a>.</p>
<p>We can think <code class="sourceCode default">TU-locals</code> as the entities which should be only usable in the module unit and the <code class="sourceCode default">exposure</code> are declarations which leak the the <code class="sourceCode default">TU-locals</code>.</p>
<p>The <code class="sourceCode default">exposure</code>s are not allowed to appear in any importable module unit (ignoring private module fragment, if any).</p>
<p>An interesting point here is, we don’t count the body of non-inline functions (and function templates) for deciding <code class="sourceCode default">exposure</code>.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">export</span> <span class="kw">module</span> a;</span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="at">static</span> <span class="dt">int</span> local() { ... }</span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="kw">export</span> <span class="dt">int</span> external() { <span class="cf">return</span> local(); }</span></code></pre></div>
<p>Here the function <code class="sourceCode default">external</code> is not an <code class="sourceCode default">exposure</code> even if its body contains a call to a <code class="sourceCode default">TU-local</code> declaration.</p>
<p><strong>This implies that the implementation shouldn’t import the bodies of non-inline functions into the consumers, even if in optimizations.</strong> Otherwise, it is problematic if the static entities get visible to other TUs.</p>
<p>Another interesting point is the bodies of function templates don’t count too.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">export</span> <span class="kw">module</span> a;</span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="at">static</span> <span class="dt">int</span> local() { ... }</span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="kw">export</span> <span class="kw">template</span>&lt;<span class="dt">int</span>&gt;</span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="dt">int</span> external() { <span class="cf">return</span> local(); }</span></code></pre></div>
<p>The above program is valid too. We don’t think the template <code class="sourceCode default">external</code> as an <code class="sourceCode default">exposure</code>. This is useful with template specializations and explicit template instantiations.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="co">// a.cppm</span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="kw">export</span> <span class="kw">module</span> a;</span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="at">static</span> <span class="dt">int</span> local() { ... }</span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="kw">export</span> <span class="kw">template</span>&lt;<span class="dt">int</span>&gt;</span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="dt">int</span> external() { <span class="cf">return</span> local(); }</span>
<span id="cb4-6"><a href="#cb4-6"></a><span class="kw">export</span> <span class="kw">template</span> <span class="dt">int</span> external&lt;<span class="dv">0</span>&gt;();</span>
<span id="cb4-7"><a href="#cb4-7"></a></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="co">// b.cpp</span></span>
<span id="cb4-9"><a href="#cb4-9"></a><span class="kw">import</span> a;</span>
<span id="cb4-10"><a href="#cb4-10"></a><span class="dt">int</span> other() {</span>
<span id="cb4-11"><a href="#cb4-11"></a>  <span class="cf">return</span> external&lt;<span class="dv">0</span>&gt;() <span class="co">// Valid.</span></span>
<span id="cb4-12"><a href="#cb4-12"></a>       + external&lt;<span class="dv">1</span>&gt;(); <span class="co">// Invalid.</span></span>
<span id="cb4-13"><a href="#cb4-13"></a>}</span></code></pre></div>
<p>The rationale behind the rule is, with explicit template instantiations, the function bodies of <code class="sourceCode default">external&lt;0&gt;()</code> is invisible to <code class="sourceCode default">b.cpp</code>. Then it is fine. But for <code class="sourceCode default">external&lt;1&gt;()</code>, its function bodies is visible to <code class="sourceCode default">b.cpp</code> due to implicit instantiations in <code class="sourceCode default">b.cpp</code>. So it is invalid.</p>
<h2 data-number="5.2" id="in-class-member-functions-is-not-implicitly-inline-in-modules-purview"><span class="header-section-number">5.2</span> in-class member functions is not implicitly inline in modules purview<a href="#in-class-member-functions-is-not-implicitly-inline-in-modules-purview" class="self-link"></a></h2>
<p>According to <a href="https://eel.is/c++draft/dcl.inline#note-4">dcl.inline/p4</a>:</p>
<blockquote>
<p>In the global module, a function defined within a class definition is implicitly inline ([class.mfct], [class.friend]).</p>
</blockquote>
<p>In other word, the in-class function definitions in the module purview is not implicitly inline.</p>
<h1 data-number="6" id="std-modules"><span class="header-section-number">6</span> Std modules<a href="#std-modules" class="self-link"></a></h1>
<p>The C++ standard library provides the <code class="sourceCode default">std</code> module and <code class="sourceCode default">std.compat</code> module <a href="https://eel.is/c++draft/std.modules">std.module</a>. This section describes the ABI requirement for these two modules.</p>
<p>The <code class="sourceCode default">std</code> and <code class="sourceCode default">std.compat</code> module are reserved module that user shouldn’t define. So it leaves the space for compilers to do special tricks for the <code class="sourceCode default">std</code> and <code class="sourceCode default">std.compat</code> modules. But no implementation does that by the time of writing.</p>
<p>It is unspecified to which module a declaration in the standard library is attached. But implementations are required to ensure that mixing #include and import does not result in conflicting attachments. This implies that the declarations in the <code class="sourceCode default">std</code> and <code class="sourceCode default">std.compat</code> module should have same linkages and the same mangled names as in the header.</p>
<h1 data-number="7" id="wishes"><span class="header-section-number">7</span> Wishes<a href="#wishes" class="self-link"></a></h1>
<p>This section describes the ABI-related wishes to modules which is not reflected in the wording of specification.</p>
<h2 data-number="7.1" id="abi-boundaries"><span class="header-section-number">7.1</span> ABI boundaries<a href="#abi-boundaries" class="self-link"></a></h2>
<p>We wish the definitions of non-inline functions and non-inline variables in modules won’t affect ABI boundaries.</p>
<p>That said, after we change the definitions of non-inline functions in an importable module unit, it is allowed to skip the recompilations of all the consumers of that module unit. While no compiler and build system implemented this yet, we think this is a promising feature to improve the compilation speed of modules.</p>
<p>This implies that the bodies of non-inline functions can’t get inlined into functions in other units without LTO, which is possible by importing the bodies as <code class="sourceCode default">available_externally</code> in LLVM.</p>
</div>
</div>
</body>
</html>
