Next: , Previous: Machine Constraints, Up: Constraints


16.8.7 定义机器特定的约束

机器特定的约束分为两类:寄存器约束和非寄存器约束。在后者中, 如果约束允许所有可能的内存或地址操作数,则应该被专门标记出来, 以便给reload更多信息。

机器特定的约束可以给定任意长度的名字,但是它们全部由字母,数字, 下划线(‘_’)和三角括号(‘< >’)组成。跟C标识符类似, 它们必须起始于字母或者下划线。

为了避免操作数约束字符串的混淆,约束的名字不能起始于任何其它约束的名字。 例如,如果x被定义为一个约束名,则不可以定义xy,反之依然。 按照这个规则,所有约束都不能起始于通用约束字母:‘E F V X g i m n o p r s’。

寄存器约束直接对应于寄存器类别。参见Register Classes。 因此它们的定义没有太多的灵活性。

— MD Expression: define_register_constraint name regclass docstring

这三个参数都是字符串常量。name为约束的名字, 将在match_operand表达式中出现。如果name为多个字母的约束, 则它的长度应该与所有起始与同一字母的约束相同。 regclass可以为相应的寄存器类别的名字(参见Register Classes), 或者一个C表达式,其值为合适的寄存器类别。如果为表达式,其必须不具有副作用, 并且不能查看操作数。通常使用表达式是为了当寄存器类别对于给定的子体系结构无效时, 将一些寄存器约束映射为NO_REGS

docstring为一条语句,介绍了约束的含义。这将在下面做进一步的解释。

非寄存器的约束更加像断言:约束定义给出一个布尔表达式,其指示是否约束匹配。

— MD Expression: define_constraint name docstring exp

namedocstring参数与define_register_constraint的相同, 但是注意docstring直接跟随name之后。exp为一个RTL表达式, 遵循在断言定义中相同的规则。详情参见Defining Predicates。如果求得为真, 则约束匹配;如果求得为假,则不匹配。约束表达式应该指示出它们可能匹配的RTL, 就像断言表达式一样。

C表达式match_test,可以访问下列变量:

op
定义操作数的RTL对象。
mode
op的机器模式。
ival
INTVAL (op)’, 如果opconst_int
hval
CONST_DOUBLE_HIGH (op)’, 如果op为整数const_double
lval
CONST_DOUBLE_LOW (op)’, 如果op为整数const_double
rval
CONST_DOUBLE_REAL_VALUE (op)’, 如果op为浮点const_double

变量*val应该只在表达式的其它部分已经验证了op为合适类型的RTL对象时, 才被使用。

大多数非寄存器约束应该使用define_constraint来定义。 其余的两个定义表达式只适合当约束匹配失败时,应该由reload单独处理的约束。

— MD Expression: define_memory_constraint name docstring exp

使用该表达式来定义匹配所有内存操作数的子集的约束:也就是, reload能够通过将操作数转换为‘(mem (reg X))’的形式使得它们 匹配。其中X为基址寄存器(通过BASE_REG_CLASS指定的寄存器类别,参见Register Classes)。

例如,在S/390上,一些指令不接受任意的内存引用,只接受那些不使用索引寄存器的。 约束字母‘Q’被定义用来表示这个类型的内存地址。 如果‘Q’使用define_memory_constraint定义, 则‘Q’约束可以处理任意内存操作数,因为reload知道在需要的时候, 它可以简单的将内存地址复制到基址寄存器中。 这与‘o’约束可以处理任意内存操作数的方式类似。

语法和语义在其它方面都与define_constraint相同。

— MD Expression: define_address_constraint name docstring exp

使用该表达式来定义匹配所有地址操作数的子集的约束:也就是, reload能够通过将操作数转换为‘(reg X)’的形式使得它们匹配。 同样X为基址寄存器。

使用define_address_constraint定义的约束只能用于address_operand断言 ,或者机器特定的同样方式的断言。它们与通用的‘p’约束类似。

语法和语义在其它方面都与define_constraint相同。

由于历史的原因, 起始于字母‘G H’的名字被保留为只匹配const_double的约束, 起始与字母‘I J K L M N O P’被保留为只匹配const_int的约束。 这在将来可能会改变。暂时的,这些名字的约束必须使用固定形式来书写, 以便genpreds能够辨别出你在做正确的事情:

     (define_constraint "[GHIJKLMNOP]..."
       "doc..."
       (and (match_code "const_int")  ; const_double for G/H
            condition...))            ; usually a match_test

可以使用起始于其它字母的名字来定义匹配const_doubleconst_int的约束。

在约束定义中的每个docstring应该是一条或多条完整的语句,使用Texinfo格式来标记。 它们目前没有被使用。在将来,它们将被复制到 GCC手册中,在机器约束这一章节, 用来替换手工维护的表格。而且,将来编译器可以使用其来给出更多有帮助的诊断信息, 当过少的asm约束选择造成重载失败时。

如果你在docstring的起始出放入伪Texinfo指令‘@internal’, 则(在将来)其将只出现在internals手册版本的机器特定约束表中。 这可以用于不应该出现在asm语句中的约束。