调用子程序的Insn具有RTL表达式代码call_insn
。这些insn必须满足特别的规则,并且它们的主体必须使用特定的RTL表达式代码call
。
(call (mem:fm addr) nbytes)
这里nbytes操作数表示传递给子程序的参数的字节数,fm是一个机器模式(其必须与在机器描述中定义的FUNCTION_MODE
相等),addr表示子程序的地址。
对于子程序没有返回值的,上面所示的call
表达式是insn的整个主体,除了insn可能还会包含use
或clobber
表达式。
对于子程序返回不是BLKmode
模式的值的,值通过硬件寄存器返回。如果该寄存器号为r,则call insn的主体看起来是这样的:
(set (reg:m r) (call (mem:fm addr) nbytes))
该RTL表达式很清楚的说明了(对于优化阶段),在该insn中有一个适当的寄存器用来接受一个有用的值。
当子程序返回BLKmode
值时,将会通过传递给子程序用来存储返回值的地址来处理。因次,call insn本身不返回任何值,具有和没有返回值一样的RTL。
在一些机器上,调用指令本身会破坏一些寄存器,例如包含了返回地址。这些机器上的call_insn
应该有一个parallel
主体,包含了call
表达式和clobber
表达式,用来指示哪些寄存器会被破坏。类似的,如果调用指令需要栈指针之外的一些寄存器,并且没有在其RTL中显示提到的,则应该用use
子表达式来指出。
被调用的函数被假设为会修改列在配置宏CALL_USED_REGISTERS
(参见Register Basics)中的所有寄存器,并且除了const函数和库函数调用外,被假设为会修改所有的内存。
直接在call_insn
之前的只是包含了use
表达式的insn,用来指示哪些寄存器用来存放函数的输入。类似的,如果不在CALL_USED_REGISTERS
中那些寄存器会被所调用的函数破坏,紧跟在call之后的包含了单独的clobber
的insn,用来指出这些寄存器。