3

在 D 中使用模板递归时,我发现经典阶乘的中间结果仍在目标文件中。我想它们也在可执行文件中......?

我可以看到实际执行的代码只包含值(或指向它的指针)但是:

不应该有一个mov语句没有无缘无故保存中间数据吗?

这是代码:

int main()
{
  static int x = factorial!(5);
  return x;//factorial!(5);
}

template factorial(int n)
{
  static if (n == 1)
    const factorial = 1;
  else
    const factorial = n * factorial!(n-1);
}

这是输出obj2asm test.o

(为方便起见:1!= 1h,2!= 2h,3!= 6h,4!= 18h,5!= 78h)

FLAT    group   
;File = test_fac_01.d
    extrn   _main
    public  _deh_beg
    public  _deh_end
    public  _tlsstart
    public  _tlsend
    public  _D11test_fac_014mainFZi1xi
    extrn   _GLOBAL_OFFSET_TABLE_
    public  _Dmain
    public  _D11test_fac_0112__ModuleInfoZ
    extrn   _Dmodule_ref
    public  _D11test_fac_017__arrayZ
    public  _D11test_fac_018__assertFiZv
    public  _D11test_fac_0115__unittest_failFiZv
    extrn   _d_array_bounds
    extrn   _d_unittestm
    extrn   _d_assertm
.text   segment
    assume  CS:.text
:
        mov EAX,offset FLAT:_D11test_fac_0112__ModuleInfoZ[018h]@32
        mov ECX,offset FLAT:_Dmodule_ref@32
        mov RDX,[RCX]
        mov [RAX],RDX
        mov [RCX],RAX
        ret
.text   ends
.data   segment
_D11test_fac_0112__ModuleInfoZ:
    db  004h,000h,000h,0ffffff80h,000h,000h,000h,000h   ;........
    db  074h,065h,073h,074h,05fh,066h,061h,063h ;test_fac
    db  05fh,030h,031h,000h,000h,000h,000h,000h ;_01.....
    db  000h,000h,000h,000h,000h,000h,000h,000h ;........
    dq  offset FLAT:_D11test_fac_0112__ModuleInfoZ@64
.data   ends
.bss    segment
.bss    ends
.rodata segment
.rodata ends
.tdata  segment
_tlsstart:
    db  000h,000h,000h,000h,000h,000h,000h,000h ;........
    db  000h,000h,000h,000h,000h,000h,000h,000h ;........
.tdata  ends
.tdata. segment
_D11test_fac_014mainFZi1xi:
    db  078h,000h,000h,000h ;x...
.tdata. ends
.text._Dmain    segment
    assume  CS:.text._Dmain
_Dmain:
        push    RBP
        mov RBP,RSP
        mov RAX,FS:[00h]
        mov RCX,_D11test_fac_014mainFZi1xi@GOTTPOFF[RIP]
        mov EAX,[RCX][RAX]
        pop RBP
        ret
        nop
        nop
        nop
.text._Dmain    ends
.data._D11test_fac_0117__T9factorialVi5Z9factorialxi    segment
_D11test_fac_0117__T9factorialVi5Z9factorialxi:
    db  078h,000h,000h,000h ;x...
.data._D11test_fac_0117__T9factorialVi5Z9factorialxi    ends
.data._D11test_fac_0117__T9factorialVi4Z9factorialxi    segment
_D11test_fac_0117__T9factorialVi4Z9factorialxi:
    db  018h,000h,000h,000h ;....
.data._D11test_fac_0117__T9factorialVi4Z9factorialxi    ends
.data._D11test_fac_0117__T9factorialVi3Z9factorialxi    segment
_D11test_fac_0117__T9factorialVi3Z9factorialxi:
    db  006h,000h,000h,000h ;....
.data._D11test_fac_0117__T9factorialVi3Z9factorialxi    ends
.data._D11test_fac_0117__T9factorialVi2Z9factorialxi    segment
_D11test_fac_0117__T9factorialVi2Z9factorialxi:
    db  002h,000h,000h,000h ;....
.data._D11test_fac_0117__T9factorialVi2Z9factorialxi    ends
.data._D11test_fac_0117__T9factorialVi1Z9factorialxi    segment
_D11test_fac_0117__T9factorialVi1Z9factorialxi:
    db  001h,000h,000h,000h ;....
.data._D11test_fac_0117__T9factorialVi1Z9factorialxi    ends
.ctors  segment
    dq  offset FLAT:@64
.ctors  ends
.text._D11test_fac_017__arrayZ  segment
    assume  CS:.text._D11test_fac_017__arrayZ
_D11test_fac_017__arrayZ:
        push    RBP
        mov RBP,RSP
        sub RSP,010h
        mov RSI,RDI
        mov RDI,offset FLAT:_D11test_fac_0112__ModuleInfoZ@64
        call      _d_array_bounds@PC32
        nop
        nop
.text._D11test_fac_017__arrayZ  ends
.text._D11test_fac_018__assertFiZv  segment
    assume  CS:.text._D11test_fac_018__assertFiZv
_D11test_fac_018__assertFiZv:
        push    RBP
        mov RBP,RSP
        sub RSP,010h
        mov RSI,RDI
        mov RDI,offset FLAT:_D11test_fac_0112__ModuleInfoZ@64
        call      _d_assertm@PC32
        nop
        nop
.text._D11test_fac_018__assertFiZv  ends
.text._D11test_fac_0115__unittest_failFiZv  segment
    assume  CS:.text._D11test_fac_0115__unittest_failFiZv
_D11test_fac_0115__unittest_failFiZv:
        push    RBP
        mov RBP,RSP
        sub RSP,010h
        mov RSI,RDI
        mov RDI,offset FLAT:_D11test_fac_0112__ModuleInfoZ@64
        call      _d_unittestm@PC32
        leave
        ret
.text._D11test_fac_0115__unittest_failFiZv  ends
    end
4

1 回答 1

4

You shouldn't use templates when what you want is compile-time function execution. Just write the function as you would and call it in a static context.

int main()
{
  static int x = factorial(5); // static causes CTFE
  return x;
}

int factorial(int n)
{
  if (n == 1)
    return 1;
  else
    return n * factorial(n-1);
}

This won't result in any extra symbols because factorial is evaluated at compile time. There are no symbols other than factorial itself. Your template trick instantiates symbols to achieve the same effect, but it's not symbols you want.

Alternatively, if you still want to use templates, but don't want symbols then you can use manifest constants via enum.

template factorial(int n)
{
  static if (n == 1)
    enum factorial = 1;
  else
    enum factorial = n * factorial!(n-1);
}

Notice the change from const to enum. enum values are purely compile-time, so they produce no symbols or data in the object files.

于 2012-09-21T17:31:05.257 回答