因此,我正在使用如下命令在 clang 14.0.6 上对此进行调查:
clang++ -O0 -S -masm=intel test.cpp
func1
结果:
.globl "?func1@@YAXXZ" # -- Begin function ?func1@@YAXXZ
.p2align 4, 0x90
"?func1@@YAXXZ": # @"?func1@@YAXXZ"
# %bb.0:
ret
# -- End function
虽然
func2
导致:
.globl "?func2@@YA?AUnothing@@XZ" # -- Begin function ?func2@@YA?AUnothing@@XZ
.p2align 4, 0x90
"?func2@@YA?AUnothing@@XZ": # @"?func2@@YA?AUnothing@@XZ"
.seh_proc "?func2@@YA?AUnothing@@XZ"
# %bb.0:
push rax
.seh_stackalloc 8
.seh_endprologue
mov al, byte ptr [rsp]
pop rcx
ret
.seh_endproc
# -- End function
主要看起来是这样的(见注释行):
main: # @main
.seh_proc main
# %bb.0:
sub rsp, 40
.seh_stackalloc 40
.seh_endprologue
call "?func1@@YAXXZ"
call "?func2@@YA?AUnothing@@XZ"
mov byte ptr [rsp + 32], al # -- This line is also a cost of 'nothing'
xor eax, eax
add rsp, 40
ret
.seh_endproc
# -- End function
我们实际上可以在这里看到一些预期的差异,因为空结构/类在 C++ 中实际上是 1 字节的长度,也可能需要额外的调试时指令来执行。
然而,重要的是看看这是否会得到适当的优化,所以继续:
clang++ -O1 -S -masm=intel test.cpp
这次功能看起来相同:
.globl "?func1@@YAXXZ" # -- Begin function ?func1@@YAXXZ
.p2align 4, 0x90
"?func1@@YAXXZ": # @"?func1@@YAXXZ"
# %bb.0:
ret
# -- End function
.globl "?func2@@YA?AUnothing@@XZ" # -- Begin function ?func2@@YA?AUnothing@@XZ
.p2align 4, 0x90
"?func2@@YA?AUnothing@@XZ": # @"?func2@@YA?AUnothing@@XZ"
# %bb.0:
ret
# -- End function
由于调用没有有意义的副作用,
main
显然被清除了:
main: # @main
# %bb.0:
xor eax, eax
ret
# -- End function
我们显然可以添加一些更复杂的逻辑,但是这次,我对在我当前有问题的范围内的结果感到满意,即,对于一个简单的内联可见范围,不返回任何内容与“返回”void 相同。