Next: , Previous: Special Accessors, Up: RTL


10.5 RTL表达式中的标记

RTL表达式包含几个标记(位域),用于特定类型的表达式。通常它们使用下列的宏来访问,并被扩展为左值。

CONSTANT_POOL_ADDRESS_P (x)
位于symbol_ref中,如果其引用了当前函数的常量池中的一部分,则非零。对于大多数目标机器,这些地址在.rodata段中,与函数完全分离,但是对于有些目标机器,这些地址是靠近函数起始处。不管哪种情况,GCC都假设这些地址可以被直接寻址,或者通过基址寄存器。其被存储在unchanging域,打印输出为‘/u’。


RTL_CONST_CALL_P (x)
位于call_insn中,表明该insn表示一个对const函数的调用。存储在unchanging域,打印输出为‘/u’。


RTL_PURE_CALL_P (x)
位于call_insn中,表明该insn表示一个对pure函数的调用。存储在return_val域,打印输出为‘/i’。


RTL_CONST_OR_PURE_CALL_P (x)
位于call_insn中,如果RTL_CONST_CALL_P或者RTL_PURE_CALL_P为真,则其为真。


RTL_LOOPING_CONST_OR_PURE_CALL_P (x)
位于call_insn中,表明该insn表示一个对const或者pure函数,可能是无限循环的调用。存储在call域,打印输出为‘/c’。只有当RTL_CONST_CALL_P或者RTL_PURE_CALL_P为真时,其才为真。


INSN_ANNULLED_BRANCH_P (x)
位于jump_insncall_insn或者insn中,表明该分支跳转被取消。参见下面关于sequence的讨论。存储在unchanging域,打印输出为‘/u’。


INSN_DELETED_P (x)
位于insn, call_insn, jump_insn, code_label, barriernote中,如果该insn被删除掉,则非零。存储在volatil域,打印输出为‘/v’。


INSN_FROM_TARGET_P (x)
位于insnjump_insn或者call_insn中,在分支延迟槽中,表明该insn是来自分支跳转的目标。如果分支insn设置了INSN_ANNULLED_BRANCH_P,则该insn只有当进行分支跳转的时候,才被执行。对于被取消的分支,如果是清除了INSN_FROM_TARGET_P,则insn只有当没有进行分支跳转的时候,才被执行。当INSN_ANNULLED_BRANCH_P没有被设置,该insn将总是被执行。存储在in_struct域,打印输出为‘/s’。


LABEL_PRESERVE_P (x)
位于code_label或者note中,表明被代码或者数据引用的该标号,对于给定的函数RTL不可见。通过非局部goto引用的标号,将设置该位。存储在in_struct域中,打印输出为‘/s’。


LABEL_REF_NONLOCAL_P (x)
位于label_refreg_label表达式中,如果其为对一个非局部标号的引用,则非零。存储在volatil域中,打印输出为‘/v’。


MEM_IN_STRUCT_P (x)
位于mem表达式中,对于引用一整个结构体,联合体,数组,或者是它们的一部分,则非零。如果是引用一个标量变量,或者是标量指针,则为零。如果该标记和MEM_SCALAR_P都被清除,则我们无法知道该mem是否在一个结构体中。这两个标记不要被同时设置。存储在in_struct域中,打印输出为‘/s’。


MEM_KEEP_ALIAS_SET_P (x)
位于mem表达式中,如果为1,则表明当访问一个部件时,应该保持该mem的别名集合不变。例如,当在一个聚合体的不可寻址部件中的时候,将其设为1。存储在jump域中,打印输出为‘/j’。


MEM_SCALAR_P (x)
位于mem表达式中,如果引用的标量,被已知不是结构体,联合体或者数组的成员,则为非零。如果是这样的引用,或者通过指针的间接引用,即便是指向标量类型,则为零,如果该标记和MEM_IN_STRUCT_P都被清除,则我们无法知道该mem是否为一个结构体。这两个标记不要被同时设置。存储在return_val域中,打印输出为‘/i’。


MEM_VOLATILE_P (x)
位于mem, asm_operandsasm_input表达式中,对于volatile内存引用,为非零。存储在volatil域中,打印输出为‘/v’。


MEM_NOTRAP_P (x)
位于mem中,对于不会产生陷阱的内存引用,为非零。存储在call域中,打印输出为‘/c’。


MEM_POINTER (x)
位于mem中,如果内存引用存放了一个指针,则非零。存储在frame_related域中,打印输出为‘/f’。


REG_FUNCTION_VALUE_P (x)
位于reg中,如果其为存放函数返回值的地方,则非零。(这只发生在硬件寄存器中。)存储在return_val域中,打印输出为‘/i’。


REG_POINTER (x)
位于reg中,如果寄存器存放一个指针,则非零。存储在frame_related域中,打印输出为‘/f’。


REG_USERVAR_P (x)
位于reg中,如果其对应于用户源代码中出现的一个变量,则非零。对于编译器内部生成的临时对象,则为零。存储在volatil域中,打印输出为‘/v’。

The same hard register may be used also for collecting the values of functions called by this one, but REG_FUNCTION_VALUE_P is zero in this kind of use.


RTX_FRAME_RELATED_P (x)
位于insn, call_insn, jump_insn, barrier, 或者set中,如果其为函数序言的一部分,用来设置栈指针,帧指针,或者保存寄存器,则为非零。对于设置用于帧指针的临时寄存器的指令,该标记也应被设置。存储在frame_related域中,打印输出为‘/f’。

特别的,在一些RISC目标机器上,对于立即数常量的大小有限制,有时不能直接通过栈指针来到达寄存器的保存区域。这种情况下,一个足够接近寄存器保存区域的临时寄存器被使用,并且正则帧地址(Canonical Frame Address)寄存器,即DWARF2的逻辑帧指针寄存器,必须(临时的)被改成该临时寄存器。所以,设置该临时寄存器的指令必须被标记为RTX_FRAME_RELATED_P

如果被标记的指令过于复杂(跟据dwarf2out_frame_debug_expr能否处理,而定义的术语),则你还必须要创建一个REG_FRAME_RELATED_EXPR注解,并附加在该指令上。该注解应该包含一个该指令执行计算的简单表达式,即dwarf2out_frame_debug_expr可以处理的。

在带有RTL序言的目标机器上,提供异常处理的支持时,会用到该标记。


MEM_READONLY_P (x)
位于mem中,如果内存是静态分配并且只读的,则非零。

在该上下文中只读,意味着在程序的生命周期中不会被修改,但是不必要是在ROM或者不可写的页中。对于后者,一个常见的例子,是共享库的全局偏移表。该表由运行时加载器初始化,所以内存在技术上是可写的,但是当控制从运行时加载器转移给应用程序时,该内存将不再被修改。

存储在unchanging域中,打印输出为‘/u’。


SCHED_GROUP_P (x)
在指令调度过程中,位于insn, call_insn或者jump_insn中,表明前一个insn必须与该insn一起调度。这用来确保特定的指令组不会被指令调度过程分隔开。例如,在call_insn之前的use insn不可以从call_insn中分开。存储在in_struct域中,打印输出为‘/s’。


SET_IS_RETURN_P (x)
对于set,如果是针对一个return,则非零。存储在jump域中,打印输出为‘/j’。


SIBLING_CALL_P (x)
对于call_insn,如果该insn为一个sibling call,则非零。存储在jump域中,打印输出为‘/j’。


STRING_POOL_ADDRESS_P (x)
对于一个symbol_ref表达式,如果其为对该函数的字符串常量池的寻址,则非零。存储在frame_related域中,打印输出为‘/f’。


SUBREG_PROMOTED_UNSIGNED_P (x)
如果subreg对于SUBREG_PROMOTED_VAR_P为非零,并且被引用的对象为零扩展,则返回一个大于零的值;如果保持为符号扩展,则为零;如果是通过ptr_extend指令,进行某种其它方式的扩展,则小于零。存储在unchanging域和volatil域中,打印输出为‘/u’和‘/v’。该宏只用于获得值,不能用于修改值。使用SUBREG_PROMOTED_UNSIGNED_SET来修改值。


SUBREG_PROMOTED_UNSIGNED_SET (x)
设置subreg中的unchangingvolatil域,来反映零扩展,符号扩展,或其它扩展。如果volatil为零,然后如果unchanging为非零,则意味着零扩展,如果为零,则意味着符号扩展。如果volatil为非零,则通过ptr_extend指令使用了其它某种扩展。


SUBREG_PROMOTED_VAR_P (x)
位于subreg中,如果当访问一个被提升为符合机器描述宏PROMOTED_MODE的(参见Storage Layout),宽机器模式的对象时,则非零。这种情况下,subreg的机器模式为对象被声明的机器模式,SUBREG_REG的机器模式为存放该对象的寄存器的机器模式。被提升的变量,在每个赋值中,总是被符号扩展或者零扩展成宽机器模式。存储在in_struct域中,打印输出为‘/s’。


SYMBOL_REF_USED (x)
位于symbol_ref中,表明x已经被使用。这通常只用于确保x只在外部被声明一次。存储在used中。


SYMBOL_REF_WEAK (x)
位于symbol_ref中,表明x已经被声明为weak。存储在return_val域中,打印输出为‘/i’。


SYMBOL_REF_FLAG (x)
位于symbol_ref中,用于机器特定目的的标记。存储在volatil域中,打印输出为‘/v’。

大多对SYMBOL_REF_FLAG的使用,是历史性的,并且可以通过SYMBOL_REF_FLAGS来归类。当然,如果目标机器需要多于一个位的存储时,对SYMBOL_REF_FLAGS的使用是强制的。


PREFETCH_SCHEDULE_BARRIER_P (x)

这些是上面的宏所引用的域:

call
mem中,1表示该内存引用不会有陷阱。

call中,1表示该pure或者const调用,可能为无限循环。

在RTL转储中,该标记被表示为‘/c’。


frame_related
insn或者set表达式中,1表示其为函数序言的一部分,设置栈寄存器,设置帧寄存器,保存寄存器,或者设置一个用于帧寄存器的临时寄存器。

reg表达式中,1表示该寄存器存放一个指针。

mem表达式中,1表示该内存引用存放一个指针。

symbol_ref表达式中,1表示该引用是对函数的字符串常量池的寻址。

在RTL转储中,该标记被表示为‘/f’。


in_struct
mem表达式中,如果所引用的内存数据为整个结构体或者数组,或者一部分,其为1;如果为(或者可能为)一个标量变量。则为0。通过C指针的引用,为0,因为指针可以指向一个标量变量。该信息允许编译器来确定别名的可能情况。

reg表达式中,如果寄存器整个生命期都包含在某个循环的测试表达式中,则为1。

subreg表达式中,1表示subreg在访问一个从更宽的机器模式进行提升的对象。

label_ref表达式中,1表示被引用的标号位于包含发现label_ref的insn的最内层循环的外面。

code_label表达式中,如果标号不能被删除,则为1。这用于其为非局部goto的目标的标号。对于已经被删除的这样的标号,使用类型为NOTE_INSN_DELETED_LABELnote来替换。

insn中,在死代码消除阶段,1表示该insn为死代码。

insn或者jump_insn中,在针对分支延迟槽中insn的reorg阶段,1表示该insn来自分支跳转的目标。

insn中,在指令调度阶段,1表示该insn必须与之前的insn一起进行调度。

在RTL转储中,该标记被表示为‘/s’。


return_val
reg表达式中,1表示寄存器包含了当且函数的返回值。对于在寄存器中传递参数的机器上,同一个寄存器编号也可以被用作参数,但是这种情况下,该标记不被设置。

mem中,1表示内存引用为一个已知不为结构体,联合体,数组的成员的标量。

symbol_ref表达式中,1表示被引用的符号为weak。

call表达式中,1表示调用是pure。

在RTL转储中,该标记被表示为‘/i’。


jump
mem表达式中,1表示当访问一个部件时,应该保持该mem的别名集不变。

set中,1表示其为一个return。

call_insn中,1表示其为一个sibling call。

在RTL转储中,该标记被表示为‘/j’。


unchanging
regmem表达式中,1表示表达式的值不会改变。

subreg表达式中,如果subreg引用了机器模式已经被提升为一个宽模式的无符号对象,则为1。

在分支指令延迟槽中的insnjump_insn中,1表示将使用一个被取消的分支。

symbol_ref表达式中,1表示该符号对函数的常量池进行寻址。

call_insn中,1表示该指令为对const函数的调用。

在RTL转储中,该标记被表示为‘/u’。


used
该标记在函数的RTL生成阶段的结尾被直接使用(不通过访问宏),来计数表达式在insns中出现的次数。出现次数大于一的表达式,根据共享结构的规则(参见Sharing),被复制。

对于reg,其被叶子寄存器重编号代码直接使用(不通过访问宏),来确保每个寄存器只被重编号一次。

symbol_ref中,其表示该符号的外部声明已经被书写了。


volatil
mem, asm_operands或者asm_input表达式中,如果内存引用是volatile的,则为1。volatile的内存引用不可以被删除,重排或者合并。

symbol_ref表达式中,其用于机器特定的目的。

reg表达式中,如果值为用户级的变量,则为1。0表示为内部的编译器临时对象。

insn中,1表示该insn已经被删除。

label_refreg_label表达式中,1表示对非局部标号的引用。

In prefetch expressions, 1 means that the containing insn is a scheduling barrier.

在RTL转储中,该标记被表示为‘/v’。