Skip to content

Commit b44b535

Browse files
committed
docs/20: whether the island header is required, and what omitting it costs
Not required by the language: the seam can declare the entry point and the island can define it, with no header, and that builds and runs. What the header buys is that the declaration exists once. Stated because the failure it prevents is the worst one available here. C language linkage does not mangle, so two copies that disagree are one symbol: the link is clean and each side reads the arguments by its own ABI. The property that forces this boundary to be extern "C" is the same property that makes a split declaration undetectable, and the three alternatives that would remove the header are listed with why none does. Both languages.
1 parent 15ce353 commit b44b535

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

docs/20-heterogeneous-builds.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,39 @@ links libstdc++ puts a second copy of the C++ runtime into a program whose own
147147
copy came from mcpp's toolchain.
148148

149149

150+
#### Is the `extern "C"` header required?
151+
152+
Not by the language. The seam can declare the entry point itself and the island
153+
can define it, with no header anywhere, and that builds and links and runs.
154+
155+
What the header buys is that the declaration exists **once**. Without it there
156+
are two copies in two compilers, and they can disagree silently:
157+
158+
```cpp
159+
// the seam
160+
extern "C" int saxpy_device(float a, const float* x, const float* y,
161+
float* out, unsigned n);
162+
// the island, after someone widened the count
163+
extern "C" int saxpy_device(float a, const float* x, const float* y,
164+
float* out, std::size_t n);
165+
```
166+
167+
C language linkage does not mangle, so those are one symbol. The link is clean
168+
and each side reads the arguments by its own ABI: no compile error, no link
169+
error, and a run that reads past the end of the arguments. The same mistake
170+
across a C++ boundary is caught by mangling at link time.
171+
172+
So the property that forces this boundary to be `extern "C"` -- the two sides do
173+
not share a C++ ABI -- is the same property that makes a split declaration
174+
undetectable. The header is the smallest artefact both a module and a device
175+
compiler can read, which is the whole of its reason for existing.
176+
177+
Three alternatives were considered and none removes it: the island cannot
178+
include the seam (a `.cppm` is not something nvcc parses), generating the header
179+
from some single source is a header with an extra step, and a module's global
180+
module fragment exports nothing the island could reach even if its compiler
181+
could read a BMI.
182+
150183
### Two kinds of lane, and only one of them has a generated interface
151184
152185
The seam above is written by hand, and the shader lane's equivalent is

docs/zh/20-heterogeneous-builds.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,35 @@ tarball 已经发出去了。设备源文件必须被显式点名。
118118
自身运行时来自 mcpp 工具链的程序里。
119119

120120

121+
#### 那个 `extern "C"` 头文件是必须的吗?
122+
123+
语言上不是。接缝可以自己声明入口点、岛自己定义它,一个头文件都不写,照样编得过、链得上、
124+
跑得起来。
125+
126+
头文件买来的是**那份声明只有一份**。没有它就有两份副本分属两个编译器,而它们可以静默地
127+
不一致:
128+
129+
```cpp
130+
// 接缝里
131+
extern "C" int saxpy_device(float a, const float* x, const float* y,
132+
float* out, unsigned n);
133+
// 岛里,在有人把计数加宽之后
134+
extern "C" int saxpy_device(float a, const float* x, const float* y,
135+
float* out, std::size_t n);
136+
```
137+
138+
C 语言链接不做名字修饰,所以这两个是同一个符号。链接是干净的,而两侧各按自己的 ABI 解释
139+
参数:没有编译错误,没有链接错误,只有一次读过了参数末尾的运行。同样的错误发生在 C++
140+
边界上会被名字修饰在链接期挡下。
141+
142+
所以**迫使这条边界必须是 `extern "C"` 的那条性质 —— 两侧不共享 C++ ABI —— 正是让声明
143+
分裂无法被发现的同一条性质**。一个普通头文件是模块和设备编译器都能读的最小共同物,这就
144+
是它存在的全部理由。
145+
146+
三条替代都试过,没有一条能去掉它:岛不能包含接缝(`.cppm` 不是 nvcc 解析的东西);从某个
147+
单一来源生成头文件就是头文件多加一步;而模块的 global module fragment 什么都不导出,即使
148+
岛的编译器能读 BMI 也够不到。
149+
121150
### 两类 lane,只有一类的接口是生成的
122151
123152
上面那个接缝是手写的,而 shader 那条 lane 的对应物是生成的。这不是不一致 ——

0 commit comments

Comments
 (0)