Previous: Conditional Expressions, Up: Operands
除非它们出现在GIMPLE_COND
的条件操作数中,否则逻辑的`and'和`or'操作符将按照下列方式进行简化:a = b && c
变成
T1 = (bool)b; if (T1 == true) T1 = (bool)c; a = T1;
注意该例子中的T1
不能为表达式临时对象,因为其具有两个不同的赋值。
所有的gimple操作数都是tree
类型的。不过只有特定类型的tree可以被用作操作数元组。函数get_gimple_rhs_class
可以进行基本的验证,其给定一个tree代码,返回一个enum
,为下列enum gimple_rhs_class
类型的值
GIMPLE_INVALID_RHS
该tree不能用作GIMPLE操作数。
GIMPLE_TERNARY_RHS
GIMPLE_BINARY_RHS
该tree为一个有效的GIMPLE二元运算。
GIMPLE_UNARY_RHS
该tree为一个有效的GIMPLE一元运算。
GIMPLE_SINGLE_RHS
该tree为单个对象,不能被拆分成更简单的操作数(例如,SSA_NAME
, VAR_DECL
, COMPONENT_REF
等等)。
该操作数类别还作为转义通口,对于那些可以被平整到操作数向量中,但是右手边会需要多于两个插槽的tree节点。例如,(a op b) ? x : y
的COND_EXPR
表达式,会被平整到使用4个插槽的操作数向量中,但是其还需要额外的处理来从c = a op b ? x : y
中判断c = a op b
。对于ASSERT_EXPR
,也有类似的情况。这些特殊情况的tree表达式应该被平整到操作数向量中。
对于在GIMPLE_BINARY_RHS
和GIMPLE_UNARY_RHS
类别中的tree节点,它们不能被直接存放在元组中。需要首先被平整,分隔到独立的部分。例如,给定GENERIC表达式
a = b + c
其tree表示为:
MODIFY_EXPR <VAR_DECL <a>, PLUS_EXPR <VAR_DECL <b>, VAR_DECL <c>>>
这种情况下,该语句的GIMPLE形式逻辑上等同于它的GENERIC形式,但是在GIMPLE中,赋值语句的右手边PLUS_EXPR
,不被表示成一个tree,替代的,PLUS_EXPR
的两个操作数子树被拿出来,并平整到GIMPLE元组中,如下:
GIMPLE_ASSIGN <PLUS_EXPR, VAR_DECL <a>, VAR_DECL <b>, VAR_DECL <c>>
操作数向量被存放在三元组结构的底部。这意味着,取决于给定语句的代码,其操作数向量相对于基本结构体的偏移量会不同。使用下列方法来访问元组操作数
返回指向语句
G
的操作数向量的指针。这通过内部称作gimple_ops_offset_
[]的表来计算。该表的索引为G
的gimple代码。当编译器被构建时,将gimple.def中定义的每个语句代码,所对应的结构体大小来填充该表。因为操作数向量在结构体的底部,所以对于gimple代码
C
,其偏移量被计算为sizeof (struct-ofC
) - sizeof (tree)。该机制对于使用
gimple_op
()的每次访问,都增加了一个内存重定向,如果这会变成瓶颈,则编译过程可以选择记住gimple_ops
()的结果,并使用它来访问操作数。
当为gimple语句增加一个新的操作数,将根据每个元组在它操作数向量中可以接受的情况来验证该操作数。这些断言由gimple_<name>_set_...()
调用。元组会使用下列断言(注意,该列表并不全):
这是条件最宽的断言。其实质上是检查t是否具有
GIMPLE_SINGLE_RHS
的gimple_rhs_class
。
返回真,如果t为一个“GIMPLE值”,其为所有非寻址的栈变量(
is_gimple_reg
返回真的变量)和常量(is_gimple_min_invariant
返回真的表达式)。
返回真,如果t为一个有效的最小不变量。这与常量不同,其特定的值在编译的时候可能不已知,但是知道其不会改变(例如,函数局部变量的地址)。